From fc021122958b4ebee9f31a8edf824e047bc17a9d Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Fri, 15 Sep 2017 22:38:45 -0500 Subject: [PATCH] Looks promising The proof of concept has been proven --- .gitignore | 4 +- .../20170104023341_InitialDb.fs | 0 src/api/App.fs | 195 ----- src/api/Data.fs | 57 -- src/api/Dependencies.fs | 48 - src/api/Entities.fs | 131 --- src/api/Extensions.fs | 16 - .../Migrations/DataContextModelSnapshot.fs | 61 -- src/api/MyPrayerJournal.fsproj | 30 - src/api/db/index.js | 18 + src/api/db/request.js | 15 + src/api/index.js | 60 ++ src/api/package.json | 21 + src/api/routes/index.js | 7 + src/api/routes/journal.js | 15 + src/api/yarn.lock | 826 ++++++++++++++++++ src/app/config/index.js | 4 +- src/app/src/api/index.js | 8 +- src/app/src/store/index.js | 5 +- 19 files changed, 974 insertions(+), 547 deletions(-) rename src/{api/Migrations => }/20170104023341_InitialDb.fs (100%) delete mode 100644 src/api/App.fs delete mode 100644 src/api/Data.fs delete mode 100644 src/api/Dependencies.fs delete mode 100644 src/api/Entities.fs delete mode 100644 src/api/Extensions.fs delete mode 100644 src/api/Migrations/DataContextModelSnapshot.fs delete mode 100644 src/api/MyPrayerJournal.fsproj create mode 100644 src/api/db/index.js create mode 100644 src/api/db/request.js create mode 100644 src/api/index.js create mode 100644 src/api/package.json create mode 100644 src/api/routes/index.js create mode 100644 src/api/routes/journal.js create mode 100644 src/api/yarn.lock diff --git a/.gitignore b/.gitignore index 1b13f4b..3814ec6 100644 --- a/.gitignore +++ b/.gitignore @@ -253,7 +253,7 @@ paket-files/ *.sln.iml # Compiled files / application -src/api/wwwroot/index.html -src/api/wwwroot/static +src/api/public/index.html +src/api/public/static src/api/appsettings.json build/ \ No newline at end of file diff --git a/src/api/Migrations/20170104023341_InitialDb.fs b/src/20170104023341_InitialDb.fs similarity index 100% rename from src/api/Migrations/20170104023341_InitialDb.fs rename to src/20170104023341_InitialDb.fs diff --git a/src/api/App.fs b/src/api/App.fs deleted file mode 100644 index e868f5c..0000000 --- a/src/api/App.fs +++ /dev/null @@ -1,195 +0,0 @@ -/// Main server module for myPrayerJournal -module MyPrayerJournal.App - -open Microsoft.EntityFrameworkCore -open Newtonsoft.Json -open Newtonsoft.Json.Linq -open System -open System.IO -open Suave -open Suave.Filters -open Suave.Operators - -// --- Types --- - -/// Auth0 settings -type Auth0Config = { - /// The domain used with Auth0 - Domain : string - /// The client Id - ClientId : string - /// The base64-encoded client secret - ClientSecret : string - /// The URL-safe base64-encoded client secret - ClientSecretJwt : string - } -with - /// An empty set of Auth0 settings - static member empty = - { Domain = "" - ClientId = "" - ClientSecret = "" - ClientSecretJwt = "" - } - -/// Application configuration -type AppConfig = { - /// PostgreSQL connection string - Conn : string - /// Auth0 settings - Auth0 : Auth0Config - } -with - static member empty = - { Conn = "" - 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 -} - - -/// Configuration instances -module Config = - - /// Application configuration - let app = - try - use sr = File.OpenText "appsettings.json" - use tr = new JsonTextReader (sr) - let settings = JToken.ReadFrom tr - let secret = settings.["auth0"].["client-secret"].ToObject() - { Conn = settings.["conn"].ToObject() - Auth0 = - { Domain = settings.["auth0"].["domain"].ToObject() - ClientId = settings.["auth0"].["client-id"].ToObject() - ClientSecret = secret - ClientSecretJwt = secret.TrimEnd('=').Replace("-", "+").Replace("_", "/") - } - } - with _ -> AppConfig.empty - - /// Custom Suave configuration - let suave = - { defaultConfig with - homeFolder = Some (Path.GetFullPath "./wwwroot/") - serverKey = Text.Encoding.UTF8.GetBytes("12345678901234567890123456789012") - bindings = [ HttpBinding.createSimple HTTP "127.0.0.1" 8084 ] - } - - -/// Authorization functions -module Auth = - - /// Shorthand for Console.WriteLine - let cw (x : string) = Console.WriteLine x - - /// Convert microtime to ticks, add difference from 1/1/1 to 1/1/1970 - let jsDate jsTicks = - DateTime(jsTicks * 10000000L).AddTicks(DateTime(1970, 1, 1).Ticks) - - /// Get the user Id (sub) from a JSON Web Token - let getIdFromToken jwt = - try - let payload = Jose.JWT.Decode(jwt, Config.app.Auth0.ClientSecretJwt) - let tokenExpires = jsDate (payload.["exp"].ToObject()) - match tokenExpires > DateTime.UtcNow with - | true -> Some (payload.["sub"].ToObject()) - | _ -> None - with ex -> - sprintf "Token Deserialization Exception - %s" (ex.GetType().FullName) |> cw - sprintf "Message - %s" ex.Message |> cw - ex.StackTrace |> cw - None - - /// Add the logged on user Id to the context if it exists - let loggedOn = - warbler (fun ctx -> - match ctx.request.header "Authorization" with - | Choice1Of2 bearer -> Writers.setUserData "user" (getIdFromToken <| bearer.Split(' ').[1]) - | _ -> Writers.setUserData "user" None) - - -// --- Support --- - -/// Get the scheme, host, and port of the URL -let schemeHostPort (req : HttpRequest) = - sprintf "%s://%s" req.url.Scheme (req.headers |> List.filter (fun x -> fst x = "host") |> List.head |> snd) - -/// Serialize an object to JSON -let toJson = JsonConvert.SerializeObject - -/// Read an item from the user state, downcast to the expected type -let read ctx key : 'value = - ctx.userState |> Map.tryFind key |> Option.map (fun x -> x :?> 'value) |> Option.get - -/// Create a new data context -let dataCtx () = - new DataContext (((DbContextOptionsBuilder()).UseNpgsql Config.app.Conn).Options) - -/// Ensure the EF context is created in the right format -let ensureDatabase () = - async { - use data = dataCtx () - do! data.Database.MigrateAsync () - } - |> Async.RunSynchronously - - -/// URL routes for myPrayerJournal -module Route = - - /// /api/journal ~ All active prayer requests for a user - let journal = "/api/journal" - -/// 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 - >=> Response.response code ((toJson >> Text.Encoding.UTF8.GetBytes) { error = error }) - - /// Journal page - let viewJournal = - context (fun ctx -> - use dataCtx = dataCtx () - let reqs = Data.Requests.allForUser (defaultArg (read ctx "user") "") dataCtx - JSON reqs) - - /// API-specific routes - let apiRoutes = - choose [ - GET >=> path Route.journal >=> viewJournal - errorJSON HttpCode.HTTP_404 "Page not found" - ] - - /// Suave application - let app = - Auth.loggedOn - >=> choose [ - path "/api" >=> apiRoutes - Files.browseHome - Files.browseFileHome "index.html" - ] - -[] -let main argv = - ensureDatabase () - startWebServer Config.suave WebParts.app - 0 diff --git a/src/api/Data.fs b/src/api/Data.fs deleted file mode 100644 index ce9e79c..0000000 --- a/src/api/Data.fs +++ /dev/null @@ -1,57 +0,0 @@ -namespace MyPrayerJournal - -open Microsoft.EntityFrameworkCore -open System.Linq -open System.Runtime.CompilerServices - -/// Data context for myPrayerJournal -type DataContext = - inherit DbContext - - (*--- CONSTRUCTORS ---*) - - new () = { inherit DbContext () } - new (options : DbContextOptions) = { inherit DbContext (options) } - - (*--- DbSet FIELDS ---*) - - [] - val mutable private requests : DbSet - [] - val mutable private history : DbSet - - (*--- DbSet PROPERTIES ---*) - - /// Prayer Requests - member this.Requests with get () = this.requests and set v = this.requests <- v - - /// History - member this.History with get () = this.history and set v = this.history <- v - - override this.OnModelCreating (modelBuilder) = - base.OnModelCreating modelBuilder - - modelBuilder.HasDefaultSchema "mpj" - |> Request.ConfigureEF - |> History.ConfigureEF - |> ignore - -/// Data access -module Data = - - /// Data access for prayer requests - module Requests = - - /// Get all prayer requests for a user - let allForUser userId (ctx : DataContext) = - query { - for req in ctx.Requests do - where (req.UserId = userId) - select req - } - |> Seq.sortBy - (fun req -> - match req.History |> Seq.sortBy (fun hist -> hist.AsOf) |> Seq.tryLast with - | Some hist -> hist.AsOf - | _ -> 0L) - |> List.ofSeq diff --git a/src/api/Dependencies.fs b/src/api/Dependencies.fs deleted file mode 100644 index 1eea244..0000000 --- a/src/api/Dependencies.fs +++ /dev/null @@ -1,48 +0,0 @@ -namespace MyPrayerJournal - -//open RethinkDb.Driver.Net - -// -- begin code lifted from #er demo -- -type ReaderM<'d, 'out> = 'd -> 'out - -module Reader = - // basic operations - let run dep (rm : ReaderM<_,_>) = rm dep - let constant (c : 'c) : ReaderM<_,'c> = fun _ -> c - // lifting of functions and state - let lift1 (f : 'd -> 'a -> 'out) : 'a -> ReaderM<'d, 'out> = fun a dep -> f dep a - let lift2 (f : 'd -> 'a -> 'b -> 'out) : 'a -> 'b -> ReaderM<'d, 'out> = fun a b dep -> f dep a b - let lift3 (f : 'd -> 'a -> 'b -> 'c -> 'out) : 'a -> 'b -> 'c -> ReaderM<'d, 'out> = fun a b c dep -> f dep a b c - let liftDep (proj : 'd2 -> 'd1) (rm : ReaderM<'d1, 'output>) : ReaderM<'d2, 'output> = proj >> rm - // functor - let fmap (f : 'a -> 'b) (g : 'c -> 'a) : ('c -> 'b) = g >> f - let map (f : 'a -> 'b) (rm : ReaderM<'d, 'a>) : ReaderM<'d,'b> = rm >> f - let () = map - // applicative-functor - let apply (f : ReaderM<'d, 'a->'b>) (rm : ReaderM<'d, 'a>) : ReaderM<'d, 'b> = - fun dep -> - let f' = run dep f - let a = run dep rm - f' a - let (<*>) = apply - // monad - let bind (rm : ReaderM<'d, 'a>) (f : 'a -> ReaderM<'d,'b>) : ReaderM<'d, 'b> = - fun dep -> - f (rm dep) - |> run dep - let (>>=) = bind - type ReaderMBuilder internal () = - member __.Bind(m, f) = m >>= f - member __.Return(v) = constant v - member __.ReturnFrom(v) = v - member __.Delay(f) = f () - let reader = ReaderMBuilder() -// -- end code lifted from #er demo -- - -(*type IDependencies = - abstract Conn : IConnection - -[] -module DependencyExtraction = - - let getConn (deps : IDependencies) = deps.Conn*) diff --git a/src/api/Entities.fs b/src/api/Entities.fs deleted file mode 100644 index 0c271df..0000000 --- a/src/api/Entities.fs +++ /dev/null @@ -1,131 +0,0 @@ -namespace MyPrayerJournal - -open Microsoft.EntityFrameworkCore; -open Newtonsoft.Json -open System -open System.Collections.Generic - -/// A prayer request -[] -type Request() = - /// The history collection (can be overridden) - let mutable historyCollection : ICollection = upcast List () - - /// The Id of the prayer request - member val RequestId = Guid.Empty with get, set - /// The Id of the user to whom the request belongs - member val UserId = "" with get, set - /// The ticks when the request was entered - member val EnteredOn = 0L with get, set - - /// The history for the prayer request - abstract History : ICollection with get, set - default this.History - with get () = historyCollection - and set v = historyCollection <- v - - static member ConfigureEF (mb : ModelBuilder) = - mb.Entity().ToTable "Request" - |> ignore - mb - - -/// A historial update to a prayer request -and [] History() = - /// The request to which this entry applies (may be overridden) - let mutable request = null - - /// The Id of the request to which this update applies - member val RequestId = Guid.Empty with get, set - /// The ticks when this entry was made - member val AsOf = 0L with get, set - /// The status of the request as of this history entry - member val Status = "" with get, set - /// The text of this history entry - member val Text = "" with get, set - - /// The request to which this entry belongs - abstract Request : Request with get, set - default this.Request - with get () = request - and set v = request <- v - - static member ConfigureEF (mb : ModelBuilder) = - mb.Entity().ToTable("History") - |> ignore - mb.Entity().HasKey(fun e -> (e.RequestId, e.AsOf) :> obj) - |> ignore - mb - -(* -/// A user -type Userr = { - /// The Id of the user - [] - Id : string - /// The user's e-mail address - Email : string - /// The user's name - Name : string - /// The time zone in which the user resides - TimeZone : string - /// The last time the user logged on - LastSeenOn : int64 -} - with - /// An empty User - static member Empty = - { Id = "" - Email = "" - Name = "" - TimeZone = "" - LastSeenOn = int64 0 } - - -/// Request history entry -type Historyy = { - /// The instant at which the update was made - AsOf : int64 - /// The action that was taken on the request - Action : string list - /// The status of the request (filled if it changed) - Status : string option - /// The text of the request (filled if it changed) - Text : string option -} - -/// A prayer request -type Requestt = { - /// The Id of the request - [] - Id : string - /// The Id of the user to whom this request belongs - UserId : string - /// The instant this request was entered - EnteredOn : int64 - /// The history for this request - History : Historyy list -} - with - /// The current status of the prayer request - member this.Status = - this.History - |> List.sortBy (fun item -> -item.AsOf) - |> List.map (fun item -> item.Status) - |> List.filter Option.isSome - |> List.map Option.get - |> List.head - /// The current text of the prayer request - member this.Text = - this.History - |> List.sortBy (fun item -> -item.AsOf) - |> List.map (fun item -> item.Text) - |> List.filter Option.isSome - |> List.map Option.get - |> List.head - member this.LastActionOn = - this.History - |> List.sortBy (fun item -> -item.AsOf) - |> List.map (fun item -> item.AsOf) - |> List.head -*) \ No newline at end of file diff --git a/src/api/Extensions.fs b/src/api/Extensions.fs deleted file mode 100644 index 8b0b7d3..0000000 --- a/src/api/Extensions.fs +++ /dev/null @@ -1,16 +0,0 @@ -[] -module MyPrayerJournal.Extensions - -open System.Threading.Tasks - -// H/T: Suave -type AsyncBuilder with - /// An extension method that overloads the standard 'Bind' of the 'async' builder. The new overload awaits on - /// a standard .NET task - member x.Bind(t : Task<'T>, f:'T -> Async<'R>) : Async<'R> = async.Bind (Async.AwaitTask t, f) - - /// An extension method that overloads the standard 'Bind' of the 'async' builder. The new overload awaits on - /// a standard .NET task which does not commpute a value - member x.Bind(t : Task, f : unit -> Async<'R>) : Async<'R> = async.Bind (Async.AwaitTask t, f) - - member x.ReturnFrom(t : Task<'T>) : Async<'T> = Async.AwaitTask t diff --git a/src/api/Migrations/DataContextModelSnapshot.fs b/src/api/Migrations/DataContextModelSnapshot.fs deleted file mode 100644 index fb05713..0000000 --- a/src/api/Migrations/DataContextModelSnapshot.fs +++ /dev/null @@ -1,61 +0,0 @@ -namespace MyPrayerJournal.Migrations - -open System -open Microsoft.EntityFrameworkCore -open Microsoft.EntityFrameworkCore.Infrastructure -open Microsoft.EntityFrameworkCore.Metadata -open Microsoft.EntityFrameworkCore.Migrations -open MyPrayerJournal - -[)>] -type DataContextModelSnapshot () = - inherit ModelSnapshot () - override this.BuildModel modelBuilder = - modelBuilder - .HasDefaultSchema("mpj") - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.0-rtm-22752") - |> ignore - - modelBuilder.Entity("MyPrayerJournal.History", - fun b -> - b.Property("RequestId") - |> ignore - b.Property("AsOf") - |> ignore - b.Property("Status") - |> ignore - b.Property("Text") - |> ignore - b.HasKey("RequestId", "AsOf") - |> ignore - b.ToTable("History") - |> ignore - ) - |> ignore - - modelBuilder.Entity("MyPrayerJournal.Request", - fun b -> - b.Property("RequestId") - .ValueGeneratedOnAdd() - |> ignore - b.Property("EnteredOn") - |> ignore - b.Property("UserId") - |> ignore - b.HasKey("RequestId") - |> ignore - b.ToTable("Request") - |> ignore - ) - |> ignore - - modelBuilder.Entity("MyPrayerJournal.History", - fun b -> - b.HasOne("MyPrayerJournal.Request", "Request") - .WithMany("History") - .HasForeignKey("RequestId") - .OnDelete(DeleteBehavior.Cascade) - |> ignore - ) - |> ignore \ No newline at end of file diff --git a/src/api/MyPrayerJournal.fsproj b/src/api/MyPrayerJournal.fsproj deleted file mode 100644 index e7dee42..0000000 --- a/src/api/MyPrayerJournal.fsproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Exe - netcoreapp2.0 - myPrayerJournal - MyPrayerJournal - 0.8.1 - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/api/db/index.js b/src/api/db/index.js new file mode 100644 index 0000000..8c3116e --- /dev/null +++ b/src/api/db/index.js @@ -0,0 +1,18 @@ +'use strict' + +const { Pool } = require('pg') +const config = require('../appsettings.json') + +const pool = new Pool(config.pgPool) + +/** + * Run a SQL query + * @param {string} text The SQL command + * @param {*[]} params The parameters for the query + */ +const query = (text, params) => pool.query(text, params) + +module.exports = { + query: query, + request: require('./request')(query) +} diff --git a/src/api/db/request.js b/src/api/db/request.js new file mode 100644 index 0000000..0a664b1 --- /dev/null +++ b/src/api/db/request.js @@ -0,0 +1,15 @@ +'use strict' + +const { Pool } = require('pg') + +module.exports = query => { + return { + /** + * Get the current requests for a user (i.e., their complete current journal) + * @param {string} userId The Id of the user + * @return The requests that make up the current journal + */ + journal: async userId => + (await query('SELECT "RequestId" FROM "Request" WHERE "UserId" = $1', [userId])).rows + } +} diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..5831078 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,60 @@ +'use strict' + +const express = require('express') + +/** Configuration for the application */ +const config = require('./appsettings.json') + +/** Express app */ +const app = express() + +const jwt = require('express-jwt') +const jwksRsa = require('jwks-rsa') + +// Authentication middleware. When used, the +// access token must exist and be verified against +// the Auth0 JSON Web Key Set +const checkJwt = jwt({ + // Dynamically provide a signing key + // based on the kid in the header and + // the singing keys provided by the JWKS endpoint. + secret: jwksRsa.expressJwtSecret({ + cache: true, + rateLimit: true, + jwksRequestsPerMinute: 5, + jwksUri: `https://${config.auth0.domain}/.well-known/jwks.json` + }), + + // Validate the audience and the issuer. + audience: config.auth0.clientId, + issuer: `https://${config.auth0.domain}/`, + algorithms: ['RS256'] +}) + +// Serve the Vue files from /public +app.use(express.static('public')) + +// Logging FTW! +app.use(require('morgan')('dev')) + +// Tie in all the API routes +require('./routes').mount(app, checkJwt) + +// Send the index.html file for what would normally get a 404 +app.use(async (req, res, next) => { + const options = { + root: __dirname + '/public/', + dotfiles: 'deny' + } + try { + await res.sendFile('index.html', options) + } + catch (err) { + return next(err) + } +}) + +// Start it up! +app.listen(config.port, () => { + console.log(`Listening on port ${config.port}`) +}) diff --git a/src/api/package.json b/src/api/package.json new file mode 100644 index 0000000..6f5fd9d --- /dev/null +++ b/src/api/package.json @@ -0,0 +1,21 @@ +{ + "name": "my-prayer-journal-api", + "private": true, + "version": "0.8.0", + "description": "Server API for myPrayerJournal", + "main": "index.js", + "author": "Daniel J. Summers ", + "license": "MIT", + "dependencies": { + "express": "^4.15.4", + "express-jwt": "^5.3.0", + "express-promise-router": "^2.0.0", + "jwks-rsa": "^1.2.0", + "morgan": "^1.8.2", + "pg": "^7.3.0" + }, + "scripts": { + "start": "node index.js", + "vue": "cd ../app && node build/build.js prod && cd ../api && node index.js" + } +} diff --git a/src/api/routes/index.js b/src/api/routes/index.js new file mode 100644 index 0000000..28c5b62 --- /dev/null +++ b/src/api/routes/index.js @@ -0,0 +1,7 @@ +'use strict' + +module.exports = { + mount: (app, checkJwt) => { + app.use('/api/journal', require('./journal')(checkJwt)) + } +} diff --git a/src/api/routes/journal.js b/src/api/routes/journal.js new file mode 100644 index 0000000..173097f --- /dev/null +++ b/src/api/routes/journal.js @@ -0,0 +1,15 @@ +'use strict' + +const Router = require('express-promise-router') +const db = require('../db') + +module.exports = checkJwt => { + let router = new Router() + + router.get('/', checkJwt, async (req, res) => { + const reqs = await db.request.journal(req.user.sub) + res.json(reqs) + }) + return router +} + diff --git a/src/api/yarn.lock b/src/api/yarn.lock new file mode 100644 index 0000000..4399873 --- /dev/null +++ b/src/api/yarn.lock @@ -0,0 +1,826 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/express-jwt@0.0.34": + version "0.0.34" + resolved "https://registry.yarnpkg.com/@types/express-jwt/-/express-jwt-0.0.34.tgz#fdbee4c6af5c0a246ef2a933f5519973c7717f02" + dependencies: + "@types/express" "*" + "@types/express-unless" "*" + +"@types/express-serve-static-core@*": + version "4.0.52" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.0.52.tgz#77ab67fffc402ff6e480c87c71d799ba79880223" + dependencies: + "@types/node" "*" + +"@types/express-unless@*": + version "0.0.31" + resolved "https://registry.yarnpkg.com/@types/express-unless/-/express-unless-0.0.31.tgz#cb6fa8a2e4d31a2ac4762d7aa00f5a258a701cb0" + dependencies: + "@types/express" "*" + +"@types/express@*": + version "4.0.37" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.0.37.tgz#625ac3765169676e01897ca47011c26375784971" + dependencies: + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + +"@types/mime@*": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.1.tgz#2cf42972d0931c1060c7d5fa6627fce6bd876f2f" + +"@types/node@*": + version "8.0.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.28.tgz#86206716f8d9251cf41692e384264cbd7058ad60" + +"@types/serve-static@*": + version "1.7.32" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.7.32.tgz#0f6732e4dab0813771dd8fc8fe14940f34728b4c" + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + +accepts@~1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" + dependencies: + mime-types "~2.1.16" + negotiator "0.6.1" + +ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +async@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +base64url@2.0.0, base64url@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-2.0.0.tgz#eac16e03ea1438eff9423d69baa36262ed1f70bb" + +basic-auth@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + +buffer-writer@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + +content-type@~1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@2.6.8, debug@^2.2.0: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +depd@1.1.1, depd@~1.1.0, depd@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ecdsa-sig-formatter@1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz#4bc926274ec3b5abb5016e7e1d60921ac262b2a1" + dependencies: + base64url "^2.0.0" + safe-buffer "^5.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +encodeurl@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +etag@~1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +express-jwt@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/express-jwt/-/express-jwt-5.3.0.tgz#3d90cd65802e6336252f19e6a3df3e149e0c5ea0" + dependencies: + async "^1.5.0" + express-unless "^0.3.0" + jsonwebtoken "^7.3.0" + lodash.set "^4.0.0" + +express-promise-router@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/express-promise-router/-/express-promise-router-2.0.0.tgz#dd8c5894b40c061c8dcc6591d2145690e99e9551" + dependencies: + is-promise "^2.1.0" + lodash "^4.13.1" + methods "^1.0.0" + +express-unless@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/express-unless/-/express-unless-0.3.1.tgz#2557c146e75beb903e2d247f9b5ba01452696e20" + +express@^4.15.4: + version "4.15.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1" + dependencies: + accepts "~1.3.3" + array-flatten "1.1.1" + content-disposition "0.5.2" + content-type "~1.0.2" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.8" + depd "~1.1.1" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.0" + finalhandler "~1.0.4" + fresh "0.5.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.1" + path-to-regexp "0.1.7" + proxy-addr "~1.1.5" + qs "6.5.0" + range-parser "~1.2.0" + send "0.15.4" + serve-static "1.12.4" + setprototypeof "1.0.3" + statuses "~1.3.1" + type-is "~1.6.15" + utils-merge "1.0.0" + vary "~1.1.1" + +extend@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extsprintf@1.3.0, extsprintf@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +finalhandler@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7" + dependencies: + debug "2.6.8" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.1" + statuses "~1.3.1" + unpipe "~1.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +forwarded@~0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + +fresh@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.0.tgz#f474ca5e6a9246d6fd8e0953cfa9b9c805afa78e" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ipaddr.js@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +isemail@1.x.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +joi@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" + dependencies: + hoek "2.x.x" + isemail "1.x.x" + moment "2.x.x" + topo "1.x.x" + +js-string-escape@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonwebtoken@^7.3.0: + version "7.4.3" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638" + dependencies: + joi "^6.10.1" + jws "^3.1.4" + lodash.once "^4.0.0" + ms "^2.0.0" + xtend "^4.0.1" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jwa@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.5.tgz#a0552ce0220742cd52e153774a32905c30e756e5" + dependencies: + base64url "2.0.0" + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.9" + safe-buffer "^5.0.1" + +jwks-rsa@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jwks-rsa/-/jwks-rsa-1.2.0.tgz#b7e925b9eac0722ad8634ad6a7e97c7daed3d4c8" + dependencies: + "@types/express-jwt" "0.0.34" + debug "^2.2.0" + limiter "^1.1.0" + lru-memoizer "^1.6.0" + ms "^2.0.0" + request "^2.73.0" + +jws@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.1.4.tgz#f9e8b9338e8a847277d6444b1464f61880e050a2" + dependencies: + base64url "^2.0.0" + jwa "^1.1.4" + safe-buffer "^5.0.1" + +limiter@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.2.tgz#229d8055891c8b11af9e0ee5200e8e09bb3dcbeb" + +lock@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/lock/-/lock-0.1.4.tgz#fec7deaef17e7c3a0a55e1da042803e25d91745d" + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + +lodash.set@^4.0.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" + +lodash@^4.13.1: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@~4.5.1: + version "4.5.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.5.1.tgz#80e8a074ca5f3893a6b1c10b2a636492d710c316" + +lru-cache@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +lru-memoizer@^1.6.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-1.11.1.tgz#0693f6100593914c02e192bf9b8d93884cbf50d3" + dependencies: + lock "~0.1.2" + lodash "~4.5.1" + lru-cache "~4.0.0" + very-fast-args "^1.1.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +methods@^1.0.0, methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + dependencies: + mime-db "~1.30.0" + +mime@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" + +moment@2.x.x: + version "2.18.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" + +morgan@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.8.2.tgz#784ac7734e4a453a9c6e6e8680a9329275c8b687" + dependencies: + basic-auth "~1.1.0" + debug "2.6.8" + depd "~1.1.0" + on-finished "~2.3.0" + on-headers "~1.0.1" + +ms@2.0.0, ms@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" + +packet-reader@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" + +parseurl@~1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + +pg-pool@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" + +pg-types@~1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.1.tgz#d64087e3903b58ffaad279e7595c52208a14c3d2" + dependencies: + postgres-array "~1.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.0" + postgres-interval "^1.1.0" + +pg@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.3.0.tgz#275e27466e54a645f6b4a16f6acadf6b849ad83b" + dependencies: + buffer-writer "1.0.1" + js-string-escape "1.0.1" + packet-reader "0.3.1" + pg-connection-string "0.1.3" + pg-pool "~2.0.3" + pg-types "~1.12.1" + pgpass "1.x" + semver "4.3.2" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + dependencies: + split "^1.0.0" + +postgres-array@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + +postgres-date@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" + +postgres-interval@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.1.tgz#acdb0f897b4b1c6e496d9d4e0a853e1c428f06f0" + dependencies: + xtend "^4.0.0" + +proxy-addr@~1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918" + dependencies: + forwarded "~0.1.0" + ipaddr.js "1.4.0" + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +request@^2.73.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +safe-buffer@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + +send@0.15.4: + version "0.15.4" + resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9" + dependencies: + debug "2.6.8" + depd "~1.1.1" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.0" + fresh "0.5.0" + http-errors "~1.6.2" + mime "1.3.4" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.1" + +serve-static@1.12.4: + version "1.12.4" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.1" + send "0.15.4" + +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +split@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + dependencies: + through "2" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +"statuses@>= 1.3.1 < 2", statuses@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +through@2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +topo@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" + dependencies: + hoek "2.x.x" + +tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-is@~1.6.15: + version "1.6.15" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.15" + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +utils-merge@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" + +uuid@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" + +vary@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +very-fast-args@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/very-fast-args/-/very-fast-args-1.1.0.tgz#e16d1d1faf8a6e596a246421fd90a77963d0b396" + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yallist@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" diff --git a/src/app/config/index.js b/src/app/config/index.js index aa74b4f..2333cd3 100644 --- a/src/app/config/index.js +++ b/src/app/config/index.js @@ -4,8 +4,8 @@ var path = require('path') module.exports = { build: { env: require('./prod.env'), - index: path.resolve(__dirname, '../../api/wwwroot/index.html'), - assetsRoot: path.resolve(__dirname, '../../api/wwwroot'), + index: path.resolve(__dirname, '../../api/public/index.html'), + assetsRoot: path.resolve(__dirname, '../../api/public'), assetsSubDirectory: 'static', assetsPublicPath: '/', productionSourceMap: true, diff --git a/src/app/src/api/index.js b/src/app/src/api/index.js index 77516c9..91b7732 100644 --- a/src/app/src/api/index.js +++ b/src/app/src/api/index.js @@ -1,7 +1,7 @@ import axios from 'axios' const http = axios.create({ - baseURL: 'http://localhost:8084/api' + baseURL: 'http://localhost:3000/api/' }) /** @@ -13,16 +13,16 @@ export default { * Set the bearer token for all future requests * @param {string} token The token to use to identify the user to the server */ - setBearer: token => { http.defaults.headers.common['Authentication'] = `Bearer ${token}` }, + setBearer: token => { http.defaults.headers.common['authorization'] = `Bearer ${token}` }, /** * Remove the bearer token */ - removeBearer: () => delete http.defaults.headers.common['Authentication'], + removeBearer: () => delete http.defaults.headers.common['authorization'], /** * Get all prayer requests and their most recent updates */ - journal: () => http.get('/journal') + journal: () => http.get('journal/') } diff --git a/src/app/src/store/index.js b/src/app/src/store/index.js index b608063..a9cb43c 100644 --- a/src/app/src/store/index.js +++ b/src/app/src/store/index.js @@ -41,10 +41,12 @@ export default new Vuex.Store({ [types.USER_LOGGED_ON] (state, user) { localStorage.setItem('user_profile', JSON.stringify(user)) state.user = user + api.setBearer(localStorage.getItem('id_token')) state.isAuthenticated = true }, [types.USER_LOGGED_OFF] (state) { state.user = {} + api.removeBearer() state.isAuthenticated = false }, [types.LOADING_JOURNAL] (state, flag) { @@ -58,10 +60,11 @@ export default new Vuex.Store({ [actions.LOAD_JOURNAL] ({ commit }) { commit(types.LOADED_JOURNAL, {}) commit(types.LOADING_JOURNAL, true) + api.setBearer(localStorage.getItem('id_token')) api.journal() .then(jrnl => { commit(types.LOADING_JOURNAL, false) - commit(types.LOADED_JOURNAL, jrnl) + commit(types.LOADED_JOURNAL, jrnl.data) }) .catch(err => { commit(types.LOADING_JOURNAL, false)