From 7b30ecffb6eb5cac48a71c6faec791464fa47147 Mon Sep 17 00:00:00 2001 From: SimonLab Date: Fri, 14 Feb 2020 16:36:12 +0100 Subject: [PATCH 1/3] display authentication google and github link, #6 --- assets/images/signin-github.png | Bin 0 -> 9144 bytes assets/images/signin-google.png | Bin 0 -> 8037 bytes elm.js | 854 ++++++++++++++++++++++++++++---- elm.json | 5 +- src/Asset.elm | 12 +- src/Main.elm | 112 ++++- 6 files changed, 869 insertions(+), 114 deletions(-) create mode 100644 assets/images/signin-github.png create mode 100644 assets/images/signin-google.png diff --git a/assets/images/signin-github.png b/assets/images/signin-github.png new file mode 100644 index 0000000000000000000000000000000000000000..20449f2a72f8c3f5b7751f966dbc440b5ad5ff2b GIT binary patch literal 9144 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 wf?kTA$T+x^QQ!ZNYZ 0) + { + var key = headerPair.substring(0, index); + var value = headerPair.substring(index + 2); + + headers = A3($elm$core$Dict$update, key, function(oldValue) { + return $elm$core$Maybe$Just($elm$core$Maybe$isJust(oldValue) + ? value + ', ' + oldValue.a + : value + ); + }, headers); + } + } + return headers; +} + + +// EXPECT + +var _Http_expect = F3(function(type, toBody, toValue) +{ + return { + $: 0, + d: type, + b: toBody, + a: toValue + }; +}); + +var _Http_mapExpect = F2(function(func, expect) +{ + return { + $: 0, + d: expect.d, + b: expect.b, + a: function(x) { return func(expect.a(x)); } + }; +}); + +function _Http_toDataView(arrayBuffer) +{ + return new DataView(arrayBuffer); +} + + +// BODY and PARTS + +var _Http_emptyBody = { $: 0 }; +var _Http_pair = F2(function(a, b) { return { $: 0, a: a, b: b }; }); + +function _Http_toFormData(parts) +{ + for (var formData = new FormData(); parts.b; parts = parts.b) // WHILE_CONS + { + var part = parts.a; + formData.append(part.a, part.b); + } + return formData; +} + +var _Http_bytesToBlob = F2(function(mime, bytes) +{ + return new Blob([bytes], { type: mime }); +}); + + +// PROGRESS + +function _Http_track(router, xhr, tracker) +{ + // TODO check out lengthComputable on loadstart event + + xhr.upload.addEventListener('progress', function(event) { + if (xhr.c) { return; } + _Scheduler_rawSpawn(A2($elm$core$Platform$sendToSelf, router, _Utils_Tuple2(tracker, $elm$http$Http$Sending({ + sent: event.loaded, + size: event.total + })))); + }); + xhr.addEventListener('progress', function(event) { + if (xhr.c) { return; } + _Scheduler_rawSpawn(A2($elm$core$Platform$sendToSelf, router, _Utils_Tuple2(tracker, $elm$http$Http$Receiving({ + received: event.loaded, + size: event.lengthComputable ? $elm$core$Maybe$Just(event.total) : $elm$core$Maybe$Nothing + })))); + }); +} + function _Url_percentEncode(string) { return encodeURIComponent(string); @@ -5167,79 +5342,77 @@ var $elm$core$Task$perform = F2( A2($elm$core$Task$map, toMessage, task))); }); var $elm$browser$Browser$application = _Browser_application; -var $author$project$Main$Model = F2( - function (key, page) { - return {key: key, page: page}; +var $author$project$Main$Model = F4( + function (key, page, authUrls, token) { + return {authUrls: authUrls, key: key, page: page, token: token}; }); var $author$project$Main$NotFound = {$: 'NotFound'}; -var $elm$core$Platform$Cmd$batch = _Platform_batch; -var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil); -var $elm$url$Url$Parser$State = F5( - function (visited, unvisited, params, frag, value) { - return {frag: frag, params: params, unvisited: unvisited, value: value, visited: visited}; +var $author$project$Main$GotAuthUrls = function (a) { + return {$: 'GotAuthUrls', a: a}; +}; +var $elm$json$Json$Decode$field = _Json_decodeField; +var $elm$json$Json$Decode$list = _Json_decodeList; +var $author$project$Main$Url = F2( + function (url, typeUrl) { + return {typeUrl: typeUrl, url: url}; }); -var $elm$url$Url$Parser$getFirstMatch = function (states) { - getFirstMatch: - while (true) { - if (!states.b) { - return $elm$core$Maybe$Nothing; - } else { - var state = states.a; - var rest = states.b; - var _v1 = state.unvisited; - if (!_v1.b) { - return $elm$core$Maybe$Just(state.value); - } else { - if ((_v1.a === '') && (!_v1.b.b)) { - return $elm$core$Maybe$Just(state.value); - } else { - var $temp$states = rest; - states = $temp$states; - continue getFirstMatch; - } - } +var $elm$json$Json$Decode$string = _Json_decodeString; +var $author$project$Main$Github = {$: 'Github'}; +var $author$project$Main$Google = {$: 'Google'}; +var $elm$json$Json$Decode$andThen = _Json_andThen; +var $elm$json$Json$Decode$fail = _Json_fail; +var $author$project$Main$urlTypeDecoder = A2( + $elm$json$Json$Decode$andThen, + function (str) { + switch (str) { + case 'google': + return $elm$json$Json$Decode$succeed($author$project$Main$Google); + case 'github': + return $elm$json$Json$Decode$succeed($author$project$Main$Github); + default: + return $elm$json$Json$Decode$fail('unkown type url'); } - } + }, + $elm$json$Json$Decode$string); +var $author$project$Main$urlDecoder = A3( + $elm$json$Json$Decode$map2, + $author$project$Main$Url, + A2($elm$json$Json$Decode$field, 'url', $elm$json$Json$Decode$string), + A2($elm$json$Json$Decode$field, 'type', $author$project$Main$urlTypeDecoder)); +var $author$project$Main$authUrlsDecoder = A2( + $elm$json$Json$Decode$field, + 'data', + $elm$json$Json$Decode$list($author$project$Main$urlDecoder)); +var $elm$json$Json$Decode$decodeString = _Json_runOnString; +var $elm$http$Http$BadStatus_ = F2( + function (a, b) { + return {$: 'BadStatus_', a: a, b: b}; + }); +var $elm$http$Http$BadUrl_ = function (a) { + return {$: 'BadUrl_', a: a}; }; -var $elm$url$Url$Parser$removeFinalEmpty = function (segments) { - if (!segments.b) { - return _List_Nil; - } else { - if ((segments.a === '') && (!segments.b.b)) { - return _List_Nil; - } else { - var segment = segments.a; - var rest = segments.b; - return A2( - $elm$core$List$cons, - segment, - $elm$url$Url$Parser$removeFinalEmpty(rest)); - } - } +var $elm$http$Http$GoodStatus_ = F2( + function (a, b) { + return {$: 'GoodStatus_', a: a, b: b}; + }); +var $elm$http$Http$NetworkError_ = {$: 'NetworkError_'}; +var $elm$http$Http$Receiving = function (a) { + return {$: 'Receiving', a: a}; }; -var $elm$url$Url$Parser$preparePath = function (path) { - var _v0 = A2($elm$core$String$split, '/', path); - if (_v0.b && (_v0.a === '')) { - var segments = _v0.b; - return $elm$url$Url$Parser$removeFinalEmpty(segments); +var $elm$http$Http$Sending = function (a) { + return {$: 'Sending', a: a}; +}; +var $elm$http$Http$Timeout_ = {$: 'Timeout_'}; +var $elm$core$Dict$RBEmpty_elm_builtin = {$: 'RBEmpty_elm_builtin'}; +var $elm$core$Dict$empty = $elm$core$Dict$RBEmpty_elm_builtin; +var $elm$core$Maybe$isJust = function (maybe) { + if (maybe.$ === 'Just') { + return true; } else { - var segments = _v0; - return $elm$url$Url$Parser$removeFinalEmpty(segments); + return false; } }; -var $elm$url$Url$Parser$addToParametersHelp = F2( - function (value, maybeList) { - if (maybeList.$ === 'Nothing') { - return $elm$core$Maybe$Just( - _List_fromArray( - [value])); - } else { - var list = maybeList.a; - return $elm$core$Maybe$Just( - A2($elm$core$List$cons, value, list)); - } - }); -var $elm$url$Url$percentDecode = _Url_percentDecode; +var $elm$core$Platform$sendToSelf = _Platform_sendToSelf; var $elm$core$Basics$compare = _Utils_compare; var $elm$core$Dict$get = F2( function (targetKey, dict) { @@ -5277,7 +5450,6 @@ var $elm$core$Dict$RBNode_elm_builtin = F5( function (a, b, c, d, e) { return {$: 'RBNode_elm_builtin', a: a, b: b, c: c, d: d, e: e}; }); -var $elm$core$Dict$RBEmpty_elm_builtin = {$: 'RBEmpty_elm_builtin'}; var $elm$core$Dict$Red = {$: 'Red'}; var $elm$core$Dict$balance = F5( function (color, key, value, left, right) { @@ -5754,6 +5926,323 @@ var $elm$core$Dict$update = F3( return A2($elm$core$Dict$remove, targetKey, dictionary); } }); +var $elm$core$Basics$composeR = F3( + function (f, g, x) { + return g( + f(x)); + }); +var $elm$http$Http$expectStringResponse = F2( + function (toMsg, toResult) { + return A3( + _Http_expect, + '', + $elm$core$Basics$identity, + A2($elm$core$Basics$composeR, toResult, toMsg)); + }); +var $elm$core$Result$mapError = F2( + function (f, result) { + if (result.$ === 'Ok') { + var v = result.a; + return $elm$core$Result$Ok(v); + } else { + var e = result.a; + return $elm$core$Result$Err( + f(e)); + } + }); +var $elm$http$Http$BadBody = function (a) { + return {$: 'BadBody', a: a}; +}; +var $elm$http$Http$BadStatus = function (a) { + return {$: 'BadStatus', a: a}; +}; +var $elm$http$Http$BadUrl = function (a) { + return {$: 'BadUrl', a: a}; +}; +var $elm$http$Http$NetworkError = {$: 'NetworkError'}; +var $elm$http$Http$Timeout = {$: 'Timeout'}; +var $elm$http$Http$resolve = F2( + function (toResult, response) { + switch (response.$) { + case 'BadUrl_': + var url = response.a; + return $elm$core$Result$Err( + $elm$http$Http$BadUrl(url)); + case 'Timeout_': + return $elm$core$Result$Err($elm$http$Http$Timeout); + case 'NetworkError_': + return $elm$core$Result$Err($elm$http$Http$NetworkError); + case 'BadStatus_': + var metadata = response.a; + return $elm$core$Result$Err( + $elm$http$Http$BadStatus(metadata.statusCode)); + default: + var body = response.b; + return A2( + $elm$core$Result$mapError, + $elm$http$Http$BadBody, + toResult(body)); + } + }); +var $elm$http$Http$expectJson = F2( + function (toMsg, decoder) { + return A2( + $elm$http$Http$expectStringResponse, + toMsg, + $elm$http$Http$resolve( + function (string) { + return A2( + $elm$core$Result$mapError, + $elm$json$Json$Decode$errorToString, + A2($elm$json$Json$Decode$decodeString, decoder, string)); + })); + }); +var $elm$http$Http$emptyBody = _Http_emptyBody; +var $elm$http$Http$Request = function (a) { + return {$: 'Request', a: a}; +}; +var $elm$http$Http$State = F2( + function (reqs, subs) { + return {reqs: reqs, subs: subs}; + }); +var $elm$http$Http$init = $elm$core$Task$succeed( + A2($elm$http$Http$State, $elm$core$Dict$empty, _List_Nil)); +var $elm$core$Process$kill = _Scheduler_kill; +var $elm$core$Process$spawn = _Scheduler_spawn; +var $elm$http$Http$updateReqs = F3( + function (router, cmds, reqs) { + updateReqs: + while (true) { + if (!cmds.b) { + return $elm$core$Task$succeed(reqs); + } else { + var cmd = cmds.a; + var otherCmds = cmds.b; + if (cmd.$ === 'Cancel') { + var tracker = cmd.a; + var _v2 = A2($elm$core$Dict$get, tracker, reqs); + if (_v2.$ === 'Nothing') { + var $temp$router = router, + $temp$cmds = otherCmds, + $temp$reqs = reqs; + router = $temp$router; + cmds = $temp$cmds; + reqs = $temp$reqs; + continue updateReqs; + } else { + var pid = _v2.a; + return A2( + $elm$core$Task$andThen, + function (_v3) { + return A3( + $elm$http$Http$updateReqs, + router, + otherCmds, + A2($elm$core$Dict$remove, tracker, reqs)); + }, + $elm$core$Process$kill(pid)); + } + } else { + var req = cmd.a; + return A2( + $elm$core$Task$andThen, + function (pid) { + var _v4 = req.tracker; + if (_v4.$ === 'Nothing') { + return A3($elm$http$Http$updateReqs, router, otherCmds, reqs); + } else { + var tracker = _v4.a; + return A3( + $elm$http$Http$updateReqs, + router, + otherCmds, + A3($elm$core$Dict$insert, tracker, pid, reqs)); + } + }, + $elm$core$Process$spawn( + A3( + _Http_toTask, + router, + $elm$core$Platform$sendToApp(router), + req))); + } + } + } + }); +var $elm$http$Http$onEffects = F4( + function (router, cmds, subs, state) { + return A2( + $elm$core$Task$andThen, + function (reqs) { + return $elm$core$Task$succeed( + A2($elm$http$Http$State, reqs, subs)); + }, + A3($elm$http$Http$updateReqs, router, cmds, state.reqs)); + }); +var $elm$core$List$maybeCons = F3( + function (f, mx, xs) { + var _v0 = f(mx); + if (_v0.$ === 'Just') { + var x = _v0.a; + return A2($elm$core$List$cons, x, xs); + } else { + return xs; + } + }); +var $elm$core$List$filterMap = F2( + function (f, xs) { + return A3( + $elm$core$List$foldr, + $elm$core$List$maybeCons(f), + _List_Nil, + xs); + }); +var $elm$http$Http$maybeSend = F4( + function (router, desiredTracker, progress, _v0) { + var actualTracker = _v0.a; + var toMsg = _v0.b; + return _Utils_eq(desiredTracker, actualTracker) ? $elm$core$Maybe$Just( + A2( + $elm$core$Platform$sendToApp, + router, + toMsg(progress))) : $elm$core$Maybe$Nothing; + }); +var $elm$http$Http$onSelfMsg = F3( + function (router, _v0, state) { + var tracker = _v0.a; + var progress = _v0.b; + return A2( + $elm$core$Task$andThen, + function (_v1) { + return $elm$core$Task$succeed(state); + }, + $elm$core$Task$sequence( + A2( + $elm$core$List$filterMap, + A3($elm$http$Http$maybeSend, router, tracker, progress), + state.subs))); + }); +var $elm$http$Http$Cancel = function (a) { + return {$: 'Cancel', a: a}; +}; +var $elm$http$Http$cmdMap = F2( + function (func, cmd) { + if (cmd.$ === 'Cancel') { + var tracker = cmd.a; + return $elm$http$Http$Cancel(tracker); + } else { + var r = cmd.a; + return $elm$http$Http$Request( + { + allowCookiesFromOtherDomains: r.allowCookiesFromOtherDomains, + body: r.body, + expect: A2(_Http_mapExpect, func, r.expect), + headers: r.headers, + method: r.method, + timeout: r.timeout, + tracker: r.tracker, + url: r.url + }); + } + }); +var $elm$http$Http$MySub = F2( + function (a, b) { + return {$: 'MySub', a: a, b: b}; + }); +var $elm$http$Http$subMap = F2( + function (func, _v0) { + var tracker = _v0.a; + var toMsg = _v0.b; + return A2( + $elm$http$Http$MySub, + tracker, + A2($elm$core$Basics$composeR, toMsg, func)); + }); +_Platform_effectManagers['Http'] = _Platform_createManager($elm$http$Http$init, $elm$http$Http$onEffects, $elm$http$Http$onSelfMsg, $elm$http$Http$cmdMap, $elm$http$Http$subMap); +var $elm$http$Http$command = _Platform_leaf('Http'); +var $elm$http$Http$subscription = _Platform_leaf('Http'); +var $elm$http$Http$request = function (r) { + return $elm$http$Http$command( + $elm$http$Http$Request( + {allowCookiesFromOtherDomains: false, body: r.body, expect: r.expect, headers: r.headers, method: r.method, timeout: r.timeout, tracker: r.tracker, url: r.url})); +}; +var $elm$http$Http$get = function (r) { + return $elm$http$Http$request( + {body: $elm$http$Http$emptyBody, expect: r.expect, headers: _List_Nil, method: 'GET', timeout: $elm$core$Maybe$Nothing, tracker: $elm$core$Maybe$Nothing, url: r.url}); +}; +var $author$project$Main$getAuthUrls = $elm$http$Http$get( + { + expect: A2($elm$http$Http$expectJson, $author$project$Main$GotAuthUrls, $author$project$Main$authUrlsDecoder), + url: 'https://appapispike.herokuapp.com/api/auth/urls' + }); +var $elm$core$Platform$Cmd$batch = _Platform_batch; +var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil); +var $elm$url$Url$Parser$State = F5( + function (visited, unvisited, params, frag, value) { + return {frag: frag, params: params, unvisited: unvisited, value: value, visited: visited}; + }); +var $elm$url$Url$Parser$getFirstMatch = function (states) { + getFirstMatch: + while (true) { + if (!states.b) { + return $elm$core$Maybe$Nothing; + } else { + var state = states.a; + var rest = states.b; + var _v1 = state.unvisited; + if (!_v1.b) { + return $elm$core$Maybe$Just(state.value); + } else { + if ((_v1.a === '') && (!_v1.b.b)) { + return $elm$core$Maybe$Just(state.value); + } else { + var $temp$states = rest; + states = $temp$states; + continue getFirstMatch; + } + } + } + } +}; +var $elm$url$Url$Parser$removeFinalEmpty = function (segments) { + if (!segments.b) { + return _List_Nil; + } else { + if ((segments.a === '') && (!segments.b.b)) { + return _List_Nil; + } else { + var segment = segments.a; + var rest = segments.b; + return A2( + $elm$core$List$cons, + segment, + $elm$url$Url$Parser$removeFinalEmpty(rest)); + } + } +}; +var $elm$url$Url$Parser$preparePath = function (path) { + var _v0 = A2($elm$core$String$split, '/', path); + if (_v0.b && (_v0.a === '')) { + var segments = _v0.b; + return $elm$url$Url$Parser$removeFinalEmpty(segments); + } else { + var segments = _v0; + return $elm$url$Url$Parser$removeFinalEmpty(segments); + } +}; +var $elm$url$Url$Parser$addToParametersHelp = F2( + function (value, maybeList) { + if (maybeList.$ === 'Nothing') { + return $elm$core$Maybe$Just( + _List_fromArray( + [value])); + } else { + var list = maybeList.a; + return $elm$core$Maybe$Just( + A2($elm$core$List$cons, value, list)); + } + }); +var $elm$url$Url$percentDecode = _Url_percentDecode; var $elm$url$Url$Parser$addParam = F2( function (segment, dict) { var _v0 = A2($elm$core$String$split, '=', segment); @@ -5782,7 +6271,6 @@ var $elm$url$Url$Parser$addParam = F2( return dict; } }); -var $elm$core$Dict$empty = $elm$core$Dict$RBEmpty_elm_builtin; var $elm$url$Url$Parser$prepareQuery = function (maybeQuery) { if (maybeQuery.$ === 'Nothing') { return $elm$core$Dict$empty; @@ -5808,7 +6296,10 @@ var $elm$url$Url$Parser$parse = F2( url.fragment, $elm$core$Basics$identity))); }); -var $author$project$Main$Auth = {$: 'Auth'}; +var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl; +var $author$project$Main$Auth = function (a) { + return {$: 'Auth', a: a}; +}; var $author$project$Main$Home = {$: 'Home'}; var $elm$url$Url$Parser$Parser = function (a) { return {$: 'Parser', a: a}; @@ -5873,6 +6364,47 @@ var $elm$url$Url$Parser$oneOf = function (parsers) { parsers); }); }; +var $elm$url$Url$Parser$query = function (_v0) { + var queryParser = _v0.a; + return $elm$url$Url$Parser$Parser( + function (_v1) { + var visited = _v1.visited; + var unvisited = _v1.unvisited; + var params = _v1.params; + var frag = _v1.frag; + var value = _v1.value; + return _List_fromArray( + [ + A5( + $elm$url$Url$Parser$State, + visited, + unvisited, + params, + frag, + value( + queryParser(params))) + ]); + }); +}; +var $elm$url$Url$Parser$slash = F2( + function (_v0, _v1) { + var parseBefore = _v0.a; + var parseAfter = _v1.a; + return $elm$url$Url$Parser$Parser( + function (state) { + return A2( + $elm$core$List$concatMap, + parseAfter, + parseBefore(state)); + }); + }); +var $elm$url$Url$Parser$questionMark = F2( + function (parser, queryParser) { + return A2( + $elm$url$Url$Parser$slash, + parser, + $elm$url$Url$Parser$query(queryParser)); + }); var $elm$url$Url$Parser$s = function (str) { return $elm$url$Url$Parser$Parser( function (_v0) { @@ -5899,6 +6431,42 @@ var $elm$url$Url$Parser$s = function (str) { } }); }; +var $elm$url$Url$Parser$Internal$Parser = function (a) { + return {$: 'Parser', a: a}; +}; +var $elm$core$Maybe$withDefault = F2( + function (_default, maybe) { + if (maybe.$ === 'Just') { + var value = maybe.a; + return value; + } else { + return _default; + } + }); +var $elm$url$Url$Parser$Query$custom = F2( + function (key, func) { + return $elm$url$Url$Parser$Internal$Parser( + function (dict) { + return func( + A2( + $elm$core$Maybe$withDefault, + _List_Nil, + A2($elm$core$Dict$get, key, dict))); + }); + }); +var $elm$url$Url$Parser$Query$string = function (key) { + return A2( + $elm$url$Url$Parser$Query$custom, + key, + function (stringList) { + if (stringList.b && (!stringList.b.b)) { + var str = stringList.a; + return $elm$core$Maybe$Just(str); + } else { + return $elm$core$Maybe$Nothing; + } + }); +}; var $elm$url$Url$Parser$top = $elm$url$Url$Parser$Parser( function (state) { return _List_fromArray( @@ -5911,18 +6479,39 @@ var $author$project$Main$routeParser = $elm$url$Url$Parser$oneOf( A2( $elm$url$Url$Parser$map, $author$project$Main$Auth, - $elm$url$Url$Parser$s('auth')) + A2( + $elm$url$Url$Parser$questionMark, + $elm$url$Url$Parser$s('auth'), + $elm$url$Url$Parser$Query$string('jwt'))) ])); var $author$project$Main$parseUrl = F2( function (url, model) { var _v0 = A2($elm$url$Url$Parser$parse, $author$project$Main$routeParser, url); if (_v0.$ === 'Just') { var page = _v0.a; - return _Utils_Tuple2( - _Utils_update( - model, - {page: page}), - $elm$core$Platform$Cmd$none); + if (page.$ === 'Auth') { + if (page.a.$ === 'Nothing') { + var _v2 = page.a; + return _Utils_Tuple2( + _Utils_update( + model, + {page: page}), + $author$project$Main$getAuthUrls); + } else { + var jwt = page.a.a; + return _Utils_Tuple2( + _Utils_update( + model, + {token: jwt}), + A2($elm$browser$Browser$Navigation$pushUrl, model.key, '/')); + } + } else { + return _Utils_Tuple2( + _Utils_update( + model, + {page: page}), + $elm$core$Platform$Cmd$none); + } } else { return _Utils_Tuple2( _Utils_update( @@ -5936,7 +6525,7 @@ var $author$project$Main$init = F3( return A2( $author$project$Main$parseUrl, url, - A2($author$project$Main$Model, key, $author$project$Main$NotFound)); + A4($author$project$Main$Model, key, $author$project$Main$NotFound, _List_Nil, '')); }); var $elm$core$Platform$Sub$batch = _Platform_batch; var $elm$core$Platform$Sub$none = $elm$core$Platform$Sub$batch(_List_Nil); @@ -5944,7 +6533,6 @@ var $author$project$Main$subscriptions = function (_v0) { return $elm$core$Platform$Sub$none; }; var $elm$browser$Browser$Navigation$load = _Browser_load; -var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl; var $elm$url$Url$addPort = F2( function (maybePort, starter) { if (maybePort.$ === 'Nothing') { @@ -5991,25 +6579,38 @@ var $elm$url$Url$toString = function (url) { }; var $author$project$Main$update = F2( function (msg, model) { - if (msg.$ === 'LinkClicked') { - var link = msg.a; - if (link.$ === 'Internal') { - var urlRequested = link.a; - return _Utils_Tuple2( - model, - A2( - $elm$browser$Browser$Navigation$pushUrl, - model.key, - $elm$url$Url$toString(urlRequested))); - } else { - var href = link.a; - return _Utils_Tuple2( - model, - $elm$browser$Browser$Navigation$load(href)); - } - } else { - var url = msg.a; - return A2($author$project$Main$parseUrl, url, model); + switch (msg.$) { + case 'LinkClicked': + var link = msg.a; + if (link.$ === 'Internal') { + var urlRequested = link.a; + return _Utils_Tuple2( + model, + A2( + $elm$browser$Browser$Navigation$pushUrl, + model.key, + $elm$url$Url$toString(urlRequested))); + } else { + var href = link.a; + return _Utils_Tuple2( + model, + $elm$browser$Browser$Navigation$load(href)); + } + case 'UrlChanged': + var url = msg.a; + return A2($author$project$Main$parseUrl, url, model); + default: + var result = msg.a; + if (result.$ === 'Ok') { + var urls = result.a; + return _Utils_Tuple2( + _Utils_update( + model, + {authUrls: urls}), + $elm$core$Platform$Cmd$none); + } else { + return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + } } }); var $elm$html$Html$a = _VirtualDom_node('a'); @@ -6022,6 +6623,7 @@ var $elm$html$Html$Attributes$stringProperty = F2( $elm$json$Json$Encode$string(string)); }); var $elm$html$Html$Attributes$class = $elm$html$Html$Attributes$stringProperty('className'); +var $elm$html$Html$div = _VirtualDom_node('div'); var $elm$html$Html$h1 = _VirtualDom_node('h1'); var $elm$html$Html$Attributes$href = function (url) { return A2( @@ -6037,6 +6639,8 @@ var $author$project$Asset$image = function (filename) { return $author$project$Asset$Image('/assets/images/' + filename); }; var $author$project$Asset$logo = $author$project$Asset$image('dwyl.png'); +var $author$project$Asset$signinGithub = $author$project$Asset$image('signin-github.png'); +var $author$project$Asset$signinGoogle = $author$project$Asset$image('signin-google.png'); var $elm$html$Html$Attributes$src = function (url) { return A2( $elm$html$Html$Attributes$stringProperty, @@ -6047,6 +6651,40 @@ var $author$project$Asset$src = function (_v0) { var url = _v0.a; return $elm$html$Html$Attributes$src(url); }; +var $author$project$Main$showAuthUrl = function (url) { + var imgSrc = function () { + var _v0 = url.typeUrl; + if (_v0.$ === 'Google') { + return $author$project$Asset$src($author$project$Asset$signinGoogle); + } else { + return $author$project$Asset$src($author$project$Asset$signinGithub); + } + }(); + return A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('tc pa2') + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$a, + _List_fromArray( + [ + $elm$html$Html$Attributes$href(url.url) + ]), + _List_fromArray( + [ + A2( + $elm$html$Html$img, + _List_fromArray( + [imgSrc]), + _List_Nil) + ])) + ])); +}; +var $elm$html$Html$span = _VirtualDom_node('span'); var $elm$virtual_dom$VirtualDom$text = _VirtualDom_text; var $elm$html$Html$text = $elm$virtual_dom$VirtualDom$text; var $author$project$Main$view = function (model) { @@ -6084,7 +6722,7 @@ var $author$project$Main$view = function (model) { [ $elm$html$Html$text('Dwyl application') ])), - A2( + $elm$core$String$isEmpty(model.token) ? A2( $elm$html$Html$a, _List_fromArray( [ @@ -6094,6 +6732,15 @@ var $author$project$Main$view = function (model) { _List_fromArray( [ $elm$html$Html$text('login/signup') + ])) : A2( + $elm$html$Html$span, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('tc db') + ]), + _List_fromArray( + [ + $elm$html$Html$text('logged in with token: ' + model.token) ])) ]); case 'Auth': @@ -6117,15 +6764,14 @@ var $author$project$Main$view = function (model) { _List_Nil) ])), A2( - $elm$html$Html$h1, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('tc') - ]), - _List_fromArray( - [ - $elm$html$Html$text('login page') - ])) + $elm$html$Html$div, + _List_Nil, + A2( + $elm$core$List$map, + function (url) { + return $author$project$Main$showAuthUrl(url); + }, + model.authUrls)) ]); default: return _List_fromArray( diff --git a/elm.json b/elm.json index c069c75..019388f 100644 --- a/elm.json +++ b/elm.json @@ -9,10 +9,13 @@ "elm/browser": "1.0.2", "elm/core": "1.0.4", "elm/html": "1.0.0", + "elm/http": "2.0.0", + "elm/json": "1.1.3", "elm/url": "1.0.0" }, "indirect": { - "elm/json": "1.1.3", + "elm/bytes": "1.0.8", + "elm/file": "1.0.5", "elm/time": "1.0.0", "elm/virtual-dom": "1.0.2" } diff --git a/src/Asset.elm b/src/Asset.elm index ad6bf60..e1674c6 100644 --- a/src/Asset.elm +++ b/src/Asset.elm @@ -1,4 +1,4 @@ -module Asset exposing (Image, logo, src) +module Asset exposing (Image, logo, signinGithub, signinGoogle, src) import Html exposing (Attribute) import Html.Attributes as Attr @@ -13,6 +13,16 @@ logo = image "dwyl.png" +signinGoogle : Image +signinGoogle = + image "signin-google.png" + + +signinGithub : Image +signinGithub = + image "signin-github.png" + + image : String -> Image image filename = Image ("/assets/images/" ++ filename) diff --git a/src/Main.elm b/src/Main.elm index 96c4c4b..9f2cb71 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -5,8 +5,11 @@ import Browser import Browser.Navigation as Nav import Html exposing (..) import Html.Attributes exposing (..) +import Http +import Json.Decode as JD import Url -import Url.Parser as Parser +import Url.Parser as Parser exposing (()) +import Url.Parser.Query as Query main : Program () Model Msg @@ -27,19 +30,21 @@ main = type Page = Home - | Auth + | Auth (Maybe String) | NotFound type alias Model = { key : Nav.Key , page : Page + , authUrls : List Url + , token : String } init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init _ url key = - parseUrl url (Model key NotFound) + parseUrl url (Model key NotFound [] "") @@ -49,6 +54,7 @@ init _ url key = type Msg = UrlChanged Url.Url | LinkClicked Browser.UrlRequest + | GotAuthUrls (Result Http.Error (List Url)) update : Msg -> Model -> ( Model, Cmd Msg ) @@ -65,12 +71,20 @@ update msg model = UrlChanged url -> parseUrl url model + GotAuthUrls result -> + case result of + Ok urls -> + ( { model | authUrls = urls }, Cmd.none ) + + Err _ -> + ( model, Cmd.none ) + routeParser : Parser.Parser (Page -> a) a routeParser = Parser.oneOf [ Parser.map Home Parser.top - , Parser.map Auth (Parser.s "auth") + , Parser.map Auth (Parser.s "auth" Query.string "jwt") ] @@ -78,7 +92,16 @@ parseUrl : Url.Url -> Model -> ( Model, Cmd Msg ) parseUrl url model = case Parser.parse routeParser url of Just page -> - ( { model | page = page }, Cmd.none ) + case page of + Auth Nothing -> + ( { model | page = page }, getAuthUrls ) + + Auth (Just jwt) -> + ( { model | token = jwt }, Nav.pushUrl model.key "/" ) + + -- redirect to home page + _ -> + ( { model | page = page }, Cmd.none ) Nothing -> ( { model | page = NotFound }, Cmd.none ) @@ -97,12 +120,16 @@ view model = Home -> [ a [ href "/" ] [ img [ Asset.src Asset.logo, class "center db pt2" ] [] ] , h1 [ class "tc" ] [ text "Dwyl application" ] - , a [ href "/auth", class "tc db" ] [ text "login/signup" ] + , if String.isEmpty model.token then + a [ href "/auth", class "tc db" ] [ text "login/signup" ] + + else + span [ class "tc db" ] [ text <| "logged in with token: " ++ model.token ] ] - Auth -> + Auth _ -> [ a [ href "/" ] [ img [ Asset.src Asset.logo, class "center db pt2" ] [] ] - , h1 [ class "tc" ] [ text "login page" ] + , div [] <| List.map (\url -> showAuthUrl url) model.authUrls ] NotFound -> @@ -110,3 +137,72 @@ view model = , h1 [ class "tc" ] [ text "page not found" ] ] } + + + +-- OAuth urls +-- convert oauth login urls (github, google) to Elm Url type + + +type alias Url = + { url : String + , typeUrl : TypeUrl + } + + +type TypeUrl + = Google + | Github + + +getAuthUrls : Cmd Msg +getAuthUrls = + Http.get + { url = "https://appapispike.herokuapp.com/api/auth/urls" + , expect = Http.expectJson GotAuthUrls authUrlsDecoder + } + + +authUrlsDecoder : JD.Decoder (List Url) +authUrlsDecoder = + JD.field "data" (JD.list urlDecoder) + + +urlDecoder : JD.Decoder Url +urlDecoder = + JD.map2 Url + (JD.field "url" JD.string) + (JD.field "type" urlTypeDecoder) + + +urlTypeDecoder : JD.Decoder TypeUrl +urlTypeDecoder = + JD.string + |> JD.andThen + (\str -> + case str of + "google" -> + JD.succeed Google + + "github" -> + JD.succeed Github + + _ -> + JD.fail "unkown type url" + ) + + +showAuthUrl : Url -> Html Msg +showAuthUrl url = + let + imgSrc = + case url.typeUrl of + Google -> + Asset.src Asset.signinGoogle + + Github -> + Asset.src Asset.signinGithub + in + div [ class "tc pa2" ] + [ a [ href url.url ] [ img [ imgSrc ] [] ] + ] From f1b8e8d822c935ad1f2c17afce6a130f6d90e5e2 Mon Sep 17 00:00:00 2001 From: SimonLab Date: Fri, 14 Feb 2020 16:46:01 +0100 Subject: [PATCH 2/3] add test for auth endpoint with jwt, #6 --- tests/MainTests.elm | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/MainTests.elm b/tests/MainTests.elm index fc9c467..34d2075 100644 --- a/tests/MainTests.elm +++ b/tests/MainTests.elm @@ -44,7 +44,25 @@ suite = Maybe.withDefault defaultUrl (Url.fromString "http://locahost/auth") in Parser.parse routeParser url - |> Expect.equal (Just Auth) + |> Expect.equal (Just (Auth Nothing)) + + , test "Test auth page with jwt" <| + \_ -> + let + defaultUrl = + { protocol = Url.Https + , host = "dwyl.com" + , port_ = Just 443 + , path = "/" + , query = Nothing + , fragment = Nothing + } + + url = + Maybe.withDefault defaultUrl (Url.fromString "http://locahost/auth?jwt=aaa.bbb.ccc") + in + Parser.parse routeParser url + |> Expect.equal (Just (Auth (Just "aaa.bbb.ccc"))) , test "Test 404 page" <| \_ -> let From 8944f4952e9ac3c08014528a657f26ff742cba32 Mon Sep 17 00:00:00 2001 From: SimonLab Date: Fri, 14 Feb 2020 16:51:37 +0100 Subject: [PATCH 3/3] format elm file, #6 --- tests/MainTests.elm | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/MainTests.elm b/tests/MainTests.elm index 34d2075..d52507d 100644 --- a/tests/MainTests.elm +++ b/tests/MainTests.elm @@ -45,7 +45,6 @@ suite = in Parser.parse routeParser url |> Expect.equal (Just (Auth Nothing)) - , test "Test auth page with jwt" <| \_ -> let