all repos

onasty @ b6505196b56e6dd59c5b122d18f0f10d3dc99998

a one-time notes service

onasty/web/src/Shared.elm (view raw)

Olexandr Smirnov Olexandr Smirnov
ss2316544@gmail.com
web: general refactor (#158)..., 11 months ago
1
module Shared exposing (Flags, Model, Msg, decoder, init, subscriptions, update)
2
3
import Api.Auth
4
import Auth.User
5
import Dict
6
import Effect exposing (Effect)
7
import Json.Decode
8
import JwtUtil
9
import Route exposing (Route)
10
import Route.Path
11
import Shared.Model
12
import Shared.Msg
13
import Task
14
import Time
15
16
17
18
-- FLAGS
19
20
21
type alias Flags =
22
    { accessToken : Maybe String
23
    , refreshToken : Maybe String
24
    , appUrl : String
25
    }
26
27
28
decoder : Json.Decode.Decoder Flags
29
decoder =
30
    Json.Decode.map3 Flags
31
        (Json.Decode.field "access_token" (Json.Decode.maybe Json.Decode.string))
32
        (Json.Decode.field "refresh_token" (Json.Decode.maybe Json.Decode.string))
33
        (Json.Decode.field "app_url" Json.Decode.string)
34
35
36
37
-- INIT
38
39
40
type alias Model =
41
    Shared.Model.Model
42
43
44
init : Result Json.Decode.Error Flags -> Route () -> ( Model, Effect Msg )
45
init flagsResult _ =
46
    let
47
        flags =
48
            flagsResult |> Result.withDefault { accessToken = Nothing, refreshToken = Nothing, appUrl = "" }
49
50
        maybeCredentials =
51
            Maybe.map2 (\access refresh -> { accessToken = access, refreshToken = refresh })
52
                flags.accessToken
53
                flags.refreshToken
54
55
        user =
56
            case maybeCredentials of
57
                Just credentials ->
58
                    Auth.User.SignedIn credentials
59
60
                Nothing ->
61
                    Auth.User.NotSignedIn
62
    in
63
    ( { user = user
64
      , timeZone = Time.utc
65
      , appURL = flags.appUrl
66
      }
67
    , Effect.batch
68
        [ Time.now |> Task.perform Shared.Msg.CheckTokenExpiration |> Effect.sendCmd
69
        , Time.here |> Task.perform Shared.Msg.GotZone |> Effect.sendCmd
70
        ]
71
    )
72
73
74
75
-- UPDATE
76
77
78
type alias Msg =
79
    Shared.Msg.Msg
80
81
82
update : Route () -> Msg -> Model -> ( Model, Effect Msg )
83
update _ msg model =
84
    case msg of
85
        Shared.Msg.GotZone timeZone ->
86
            ( { model | timeZone = timeZone }, Effect.none )
87
88
        Shared.Msg.Logout ->
89
            ( { model | user = Auth.User.NotSignedIn }, Effect.clearUser )
90
91
        Shared.Msg.SignedIn credentials ->
92
            ( { model | user = Auth.User.SignedIn credentials }
93
            , Effect.batch
94
                [ Effect.pushRoute
95
                    { path = Route.Path.Home_
96
                    , query = Dict.empty
97
                    , hash = Nothing
98
                    }
99
                , Effect.saveUser credentials.accessToken credentials.refreshToken
100
                ]
101
            )
102
103
        Shared.Msg.CheckTokenExpiration now ->
104
            case model.user of
105
                Auth.User.SignedIn credentials ->
106
                    if JwtUtil.isExpired now credentials.accessToken then
107
                        ( model, Effect.refreshTokens )
108
109
                    else
110
                        ( model, Effect.none )
111
112
                _ ->
113
                    ( model, Effect.none )
114
115
        Shared.Msg.TriggerTokenRefresh ->
116
            case model.user of
117
                Auth.User.SignedIn credentials ->
118
                    ( { model | user = Auth.User.RefreshingTokens }
119
                    , Api.Auth.refreshToken
120
                        { onResponse = Shared.Msg.ApiRefreshTokensResponded
121
                        , refreshToken = credentials.refreshToken
122
                        }
123
                    )
124
125
                _ ->
126
                    ( model, Effect.none )
127
128
        Shared.Msg.ApiRefreshTokensResponded (Ok credentials) ->
129
            ( { model | user = Auth.User.SignedIn credentials }
130
            , Effect.saveUser credentials.accessToken credentials.refreshToken
131
            )
132
133
        Shared.Msg.ApiRefreshTokensResponded (Err _) ->
134
            ( { model | user = Auth.User.NotSignedIn }, Effect.clearUser )
135
136
137
138
-- SUBSCRIPTIONS
139
140
141
subscriptions : Route () -> Model -> Sub Msg
142
subscriptions _ _ =
143
    Time.every (30 * 1000) Shared.Msg.CheckTokenExpiration