Skip to content

Commit c9e7e8c

Browse files
committed
OAuth is working!
1 parent b1e5bbc commit c9e7e8c

File tree

16 files changed

+557
-95
lines changed

16 files changed

+557
-95
lines changed

elm-land.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"html": { "lang": "en" },
1616
"head": {}
1717
},
18-
"title": "Elm Land",
18+
"title": "Jangle",
1919
"meta": [
2020
{ "charset": "UTF-8" },
2121
{ "http-equiv": "X-UA-Compatible", "content": "IE=edge" },

src/Auth.elm

+12-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Dict
66
import Route exposing (Route)
77
import Route.Path
88
import Shared
9+
import Shared.Model
910
import View exposing (View)
1011

1112

@@ -18,10 +19,16 @@ type alias User =
1819
onPageLoad : Shared.Model -> Route () -> Auth.Action.Action User
1920
onPageLoad shared route =
2021
case shared.user of
21-
Just user ->
22+
Auth.User.SignedIn user ->
2223
Auth.Action.loadPageWithUser user
2324

24-
Nothing ->
25+
Auth.User.FetchingUserDetails response ->
26+
Auth.Action.showLoadingPage
27+
{ title = "Signing in..."
28+
, body = []
29+
}
30+
31+
Auth.User.NotSignedIn ->
2532
Auth.Action.pushRoute
2633
{ path = Route.Path.SignIn
2734
, query = Dict.empty
@@ -33,4 +40,6 @@ onPageLoad shared route =
3340
-}
3441
viewLoadingPage : Shared.Model -> Route () -> View Never
3542
viewLoadingPage shared route =
36-
View.fromString "Loading..."
43+
{ title = "Signing in..."
44+
, body = []
45+
}

src/Auth/User.elm

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1-
module Auth.User exposing (User)
1+
module Auth.User exposing (SignInStatus(..), User)
2+
3+
import Supabase.OAuthResponse
4+
5+
6+
type SignInStatus
7+
= NotSignedIn
8+
| FetchingUserDetails Supabase.OAuthResponse.OAuthResponse
9+
| SignedIn User
210

311

412
type alias User =
5-
{ name : String
13+
{ id : String
14+
, name : String
615
, email : String
716
, image : Maybe String
17+
, supabaseToken : String
18+
, githubToken : Maybe String
19+
, githubUsername : Maybe String
820
}

src/Effect.elm

+112-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
module Effect exposing
1+
port module Effect exposing
22
( Effect
33
, none, batch
44
, sendCmd, sendMsg
55
, pushRoute, replaceRoute, loadExternalUrl
66
, map, toCmd
7+
, saveOAuthResponse
8+
, fetchSupabaseUser
79
)
810

911
{-|
@@ -15,14 +17,25 @@ module Effect exposing
1517
1618
@docs map, toCmd
1719
20+
21+
## Custom effects
22+
23+
@docs saveOAuthResponse
24+
@docs fetchSupabaseUser
25+
1826
-}
1927

28+
import Auth.User
2029
import Browser.Navigation
2130
import Dict exposing (Dict)
31+
import Json.Encode
2232
import Route exposing (Route)
2333
import Route.Path
2434
import Shared.Model
2535
import Shared.Msg
36+
import Supabase.Auth
37+
import Supabase.Context
38+
import Supabase.OAuthResponse
2639
import Task
2740
import Url exposing (Url)
2841

@@ -38,6 +51,13 @@ type Effect msg
3851
| LoadExternalUrl String
3952
-- SHARED
4053
| SendSharedMsg Shared.Msg.Msg
54+
-- LOCAL STORAGE
55+
| Save
56+
{ key : String
57+
, value : Json.Encode.Value
58+
}
59+
-- SUPABASE
60+
| Supabase SupabaseRequest
4161

4262

4363

@@ -111,6 +131,31 @@ loadExternalUrl =
111131

112132

113133

134+
-- LOCAL STORAGE
135+
136+
137+
saveOAuthResponse : Supabase.OAuthResponse.OAuthResponse -> Effect msg
138+
saveOAuthResponse oauthResponse =
139+
Save
140+
{ key = "oAuthResponse"
141+
, value = Supabase.OAuthResponse.encode oauthResponse
142+
}
143+
144+
145+
146+
-- SUPABASE
147+
148+
149+
type SupabaseRequest
150+
= FetchSupabaseUser
151+
152+
153+
fetchSupabaseUser : Effect msg
154+
fetchSupabaseUser =
155+
Supabase FetchSupabaseUser
156+
157+
158+
114159
-- INTERNALS
115160

116161

@@ -141,6 +186,12 @@ map fn effect =
141186
SendSharedMsg sharedMsg ->
142187
SendSharedMsg sharedMsg
143188

189+
Supabase request ->
190+
Supabase request
191+
192+
Save data ->
193+
Save data
194+
144195

145196
{-| Elm Land depends on this function to perform your effects.
146197
-}
@@ -177,3 +228,63 @@ toCmd options effect =
177228
SendSharedMsg sharedMsg ->
178229
Task.succeed sharedMsg
179230
|> Task.perform options.fromSharedMsg
231+
232+
Save { key, value } ->
233+
outgoing
234+
{ tag = "SAVE"
235+
, data =
236+
Json.Encode.object
237+
[ ( "key", Json.Encode.string key )
238+
, ( "value", value )
239+
]
240+
}
241+
242+
Supabase request ->
243+
let
244+
userToken : Maybe String
245+
userToken =
246+
case options.shared.user of
247+
Auth.User.NotSignedIn ->
248+
Nothing
249+
250+
Auth.User.FetchingUserDetails oAuthResponse ->
251+
Just oAuthResponse.accessToken
252+
253+
Auth.User.SignedIn user ->
254+
Just user.supabaseToken
255+
256+
context : Supabase.Context.Context
257+
context =
258+
Supabase.Context.create
259+
{ apiKey = options.shared.supabase.apiKey
260+
, url = options.shared.supabase.url
261+
}
262+
|> withUserToken
263+
264+
withUserToken :
265+
Supabase.Context.Context
266+
-> Supabase.Context.Context
267+
withUserToken context_ =
268+
case userToken of
269+
Just token ->
270+
context_
271+
|> Supabase.Context.withUserToken token
272+
273+
Nothing ->
274+
context_
275+
in
276+
case request of
277+
FetchSupabaseUser ->
278+
Supabase.Auth.getUserData
279+
{ onResponse =
280+
Shared.Msg.SupabaseUserApiResponded
281+
>> options.fromSharedMsg
282+
}
283+
context
284+
285+
286+
port outgoing :
287+
{ tag : String
288+
, data : Json.Encode.Value
289+
}
290+
-> Cmd msg

src/Pages/Home_.elm

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ subscriptions model =
8888

8989
view : Path -> Model -> View Msg
9090
view path model =
91-
{ title = "Homepage"
91+
{ title = "Jangle | Dashboard"
9292
, body =
9393
[ div [ Css.col, Css.pad_32, Css.gap_16, Css.align_left ]
9494
[ h1 [ Css.font_h1 ] [ text ("Counter: " ++ String.fromInt model.counter) ]

src/Pages/NotFound_.elm

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Pages.NotFound_ exposing (Model, Msg, page)
22

3+
import Css
34
import Effect exposing (Effect)
45
import Html exposing (..)
56
import Page exposing (Page)
@@ -66,4 +67,10 @@ subscriptions model =
6667

6768
view : Model -> View Msg
6869
view model =
69-
View.fromString "Page not found"
70+
{ title = "Jangle | 404"
71+
, body =
72+
[ div [ Css.row, Css.h_fill, Css.align_center ]
73+
[ text "Page not found"
74+
]
75+
]
76+
}

src/Pages/Projects/ProjectId_/Content/TypeId_.elm

+5-2
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,12 @@ subscriptions model =
7979
-- VIEW
8080

8181

82-
view : Route any -> Model -> View Msg
82+
view :
83+
Route { projectId : String, typeId : String }
84+
-> Model
85+
-> View Msg
8386
view route model =
84-
{ title = "Pages.Projects.ProjectId_.Content.TypeId_"
87+
{ title = "Jangle | " ++ route.params.typeId
8588
, body =
8689
[ div [ Css.col, Css.pad_32, Css.gap_16, Css.align_left ]
8790
[ text "Hello from the content page!"

src/Pages/SignIn.elm

+27-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
module Pages.SignIn exposing (Model, Msg, page)
22

3+
import Components.Button
4+
import Components.Icon
5+
import Components.JangleLogo
6+
import Css
37
import Effect exposing (Effect)
4-
import Route exposing (Route)
5-
import Html
8+
import Html exposing (..)
69
import Page exposing (Page)
10+
import Route exposing (Route)
711
import Shared
812
import View exposing (View)
913

@@ -14,7 +18,7 @@ page shared route =
1418
{ init = init
1519
, update = update
1620
, subscriptions = subscriptions
17-
, view = view
21+
, view = view shared
1822
}
1923

2024

@@ -38,13 +42,13 @@ init () =
3842

3943

4044
type Msg
41-
= ExampleMsgReplaceMe
45+
= UserClickedSignIn
4246

4347

4448
update : Msg -> Model -> ( Model, Effect Msg )
4549
update msg model =
4650
case msg of
47-
ExampleMsgReplaceMe ->
51+
UserClickedSignIn ->
4852
( model
4953
, Effect.none
5054
)
@@ -63,8 +67,22 @@ subscriptions model =
6367
-- VIEW
6468

6569

66-
view : Model -> View Msg
67-
view model =
68-
{ title = "Pages.SignIn"
69-
, body = [ Html.text "/sign-in" ]
70+
view : Shared.Model -> Model -> View Msg
71+
view shared model =
72+
let
73+
gitHubOAuthUrl : String
74+
gitHubOAuthUrl =
75+
shared.supabase.url ++ "/auth/v1/authorize?provider=github"
76+
in
77+
{ title = "Jangle | Sign in"
78+
, body =
79+
[ div [ Css.h_fill, Css.col, Css.align_center, Css.gap_16 ]
80+
[ Components.JangleLogo.viewLarge
81+
, Components.Button.new { label = "Sign in with GitHub" }
82+
|> Components.Button.withStyleSecondary
83+
|> Components.Button.withIcon Components.Icon.GitHub
84+
|> Components.Button.withHref gitHubOAuthUrl
85+
|> Components.Button.view
86+
]
87+
]
7088
}

0 commit comments

Comments
 (0)