Extract access token value on r0.0.0 login endpoint
parent
6e89371845
commit
c84bb2a1ef
|
@ -9,7 +9,6 @@ This module looks for the right homeserver address.
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
import Internal.Api.Api as A
|
|
||||||
import Internal.Api.Chain as C
|
import Internal.Api.Chain as C
|
||||||
import Internal.Api.Request as R
|
import Internal.Api.Request as R
|
||||||
import Internal.Config.Leaks as L
|
import Internal.Config.Leaks as L
|
||||||
|
@ -20,7 +19,7 @@ import Internal.Values.Envelope as E
|
||||||
import Internal.Values.Vault as V
|
import Internal.Values.Vault as V
|
||||||
|
|
||||||
|
|
||||||
baseUrl : BaseUrlInput -> C.TaskChain R.Error (E.EnvelopeUpdate V.VaultUpdate) (Phantom ph) (Phantom { ph | baseUrl : () })
|
baseUrl : BaseUrlInput -> C.TaskChain R.Error (E.EnvelopeUpdate V.VaultUpdate) ph { ph | baseUrl : () }
|
||||||
baseUrl data =
|
baseUrl data =
|
||||||
R.toChain
|
R.toChain
|
||||||
{ logHttp =
|
{ logHttp =
|
||||||
|
@ -65,10 +64,6 @@ type alias BaseUrlInput =
|
||||||
{ url : String }
|
{ url : String }
|
||||||
|
|
||||||
|
|
||||||
type alias Phantom a =
|
|
||||||
a
|
|
||||||
|
|
||||||
|
|
||||||
type alias DiscoveryInformation =
|
type alias DiscoveryInformation =
|
||||||
{ homeserver : HomeserverInformation
|
{ homeserver : HomeserverInformation
|
||||||
, identityServer : Maybe IdentityServerInformation
|
, identityServer : Maybe IdentityServerInformation
|
||||||
|
|
|
@ -56,11 +56,11 @@ type alias LoginWithUsernameAndPasswordOutputV1 =
|
||||||
|
|
||||||
|
|
||||||
type alias PhantomV1 a =
|
type alias PhantomV1 a =
|
||||||
{ a | baseUrl : () }
|
{ a | baseUrl : (), now : () }
|
||||||
|
|
||||||
|
|
||||||
loginWithUsernameAndPasswordV1 : LoginWithUsernameAndPasswordInputV1 a -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
|
loginWithUsernameAndPasswordV1 : LoginWithUsernameAndPasswordInputV1 a -> A.TaskChain (PhantomV1 a) (PhantomV1 { a | accessToken : () })
|
||||||
loginWithUsernameAndPasswordV1 { username, password } =
|
loginWithUsernameAndPasswordV1 { username, password } context =
|
||||||
A.request
|
A.request
|
||||||
{ attributes =
|
{ attributes =
|
||||||
[ R.bodyString "password" password
|
[ R.bodyString "password" password
|
||||||
|
@ -77,12 +77,18 @@ loginWithUsernameAndPasswordV1 { username, password } =
|
||||||
, toUpdate =
|
, toUpdate =
|
||||||
\out ->
|
\out ->
|
||||||
( E.More
|
( E.More
|
||||||
[ E.SetAccessToken out.accessToken
|
[ E.SetAccessToken
|
||||||
-- , E.SetRefreshToken out.refreshToken
|
{ created = Context.getNow context
|
||||||
|
, expiryMs = Nothing
|
||||||
|
, lastUsed = Context.getNow context
|
||||||
|
, refresh = out.refreshToken
|
||||||
|
, value = out.accessToken
|
||||||
|
}
|
||||||
]
|
]
|
||||||
, []
|
, []
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
context
|
||||||
|
|
||||||
|
|
||||||
coderV1 : Json.Coder LoginWithUsernameAndPasswordOutputV1
|
coderV1 : Json.Coder LoginWithUsernameAndPasswordOutputV1
|
||||||
|
|
|
@ -90,7 +90,7 @@ getVersions c =
|
||||||
{-| Establish a Task Chain context where the base URL and supported list of
|
{-| Establish a Task Chain context where the base URL and supported list of
|
||||||
versions are known.
|
versions are known.
|
||||||
-}
|
-}
|
||||||
makeVB : UFTask {} { a | baseUrl : (), versions : () }
|
makeVB : UFTask a { a | baseUrl : (), versions : () }
|
||||||
makeVB =
|
makeVB =
|
||||||
C.andThen getVersions getBaseUrl
|
C.andThen getVersions getBaseUrl
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module Internal.Tools.Timestamp exposing
|
module Internal.Tools.Timestamp exposing
|
||||||
( Timestamp
|
( Timestamp
|
||||||
|
, add, toMs
|
||||||
, coder, encode, decoder
|
, coder, encode, decoder
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,6 +13,11 @@ elm/time. This module offers ways to work with the timestamp in meaningful ways.
|
||||||
@docs Timestamp
|
@docs Timestamp
|
||||||
|
|
||||||
|
|
||||||
|
## Calculate
|
||||||
|
|
||||||
|
@docs add, toMs
|
||||||
|
|
||||||
|
|
||||||
## JSON coders
|
## JSON coders
|
||||||
|
|
||||||
@docs coder, encode, decoder
|
@docs coder, encode, decoder
|
||||||
|
@ -28,6 +34,15 @@ type alias Timestamp =
|
||||||
Time.Posix
|
Time.Posix
|
||||||
|
|
||||||
|
|
||||||
|
{-| Add a given number of miliseconds to a given Timestamp.
|
||||||
|
-}
|
||||||
|
add : Int -> Timestamp -> Timestamp
|
||||||
|
add m =
|
||||||
|
Time.posixToMillis
|
||||||
|
>> (+) m
|
||||||
|
>> Time.millisToPosix
|
||||||
|
|
||||||
|
|
||||||
{-| Create a Json coder
|
{-| Create a Json coder
|
||||||
-}
|
-}
|
||||||
coder : Json.Coder Timestamp
|
coder : Json.Coder Timestamp
|
||||||
|
@ -55,3 +70,10 @@ encode =
|
||||||
decoder : Json.Decoder Timestamp
|
decoder : Json.Decoder Timestamp
|
||||||
decoder =
|
decoder =
|
||||||
Json.decode coder
|
Json.decode coder
|
||||||
|
|
||||||
|
|
||||||
|
{-| Turn a Timestamp into a number of miliseconds
|
||||||
|
-}
|
||||||
|
toMs : Timestamp -> Int
|
||||||
|
toMs =
|
||||||
|
Time.posixToMillis
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
module Internal.Values.Context exposing
|
module Internal.Values.Context exposing
|
||||||
( Context, init, coder, encode, decoder
|
( Context, AccessToken, init, coder, encode, decoder
|
||||||
, APIContext, apiFormat, fromApiFormat
|
, APIContext, apiFormat, fromApiFormat
|
||||||
, setAccessToken, getAccessToken
|
, setAccessToken, getAccessToken
|
||||||
, setBaseUrl, getBaseUrl
|
, setBaseUrl, getBaseUrl
|
||||||
|
, setNow, getNow
|
||||||
, setTransaction, getTransaction
|
, setTransaction, getTransaction
|
||||||
, Versions, setVersions, getVersions
|
, Versions, setVersions, getVersions
|
||||||
)
|
)
|
||||||
|
@ -14,7 +15,7 @@ the Matrix API.
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
@docs Context, init, coder, encode, decoder
|
@docs Context, AccessToken, init, coder, encode, decoder
|
||||||
|
|
||||||
|
|
||||||
## APIContext
|
## APIContext
|
||||||
|
@ -38,6 +39,11 @@ information that can be inserted.
|
||||||
@docs setBaseUrl, getBaseUrl
|
@docs setBaseUrl, getBaseUrl
|
||||||
|
|
||||||
|
|
||||||
|
### Timestamp
|
||||||
|
|
||||||
|
@docs setNow, getNow
|
||||||
|
|
||||||
|
|
||||||
### Transaction id
|
### Transaction id
|
||||||
|
|
||||||
@docs setTransaction, getTransaction
|
@docs setTransaction, getTransaction
|
||||||
|
@ -51,17 +57,33 @@ information that can be inserted.
|
||||||
|
|
||||||
import Internal.Config.Leaks as L
|
import Internal.Config.Leaks as L
|
||||||
import Internal.Config.Text as Text
|
import Internal.Config.Text as Text
|
||||||
|
import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
|
||||||
import Internal.Tools.Json as Json
|
import Internal.Tools.Json as Json
|
||||||
|
import Internal.Tools.Timestamp as Timestamp exposing (Timestamp)
|
||||||
import Json.Encode as E
|
import Json.Encode as E
|
||||||
import Set exposing (Set)
|
import Set exposing (Set)
|
||||||
|
import Time
|
||||||
|
|
||||||
|
|
||||||
|
{-| The Access Token is a combination of access tokens, values and refresh
|
||||||
|
tokens that contain and summarizes all properties of a known access token.
|
||||||
|
-}
|
||||||
|
type alias AccessToken =
|
||||||
|
{ created : Timestamp
|
||||||
|
, expiryMs : Maybe Int
|
||||||
|
, lastUsed : Timestamp
|
||||||
|
, refresh : Maybe String
|
||||||
|
, value : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
{-| The Context type stores all the information in the Vault. This data type is
|
{-| The Context type stores all the information in the Vault. This data type is
|
||||||
static and hence can be passed on easily.
|
static and hence can be passed on easily.
|
||||||
-}
|
-}
|
||||||
type alias Context =
|
type alias Context =
|
||||||
{ accessToken : Maybe String
|
{ accessTokens : Hashdict AccessToken
|
||||||
, baseUrl : Maybe String
|
, baseUrl : Maybe String
|
||||||
|
, now : Maybe Timestamp
|
||||||
, password : Maybe String
|
, password : Maybe String
|
||||||
, refreshToken : Maybe String
|
, refreshToken : Maybe String
|
||||||
, serverName : String
|
, serverName : String
|
||||||
|
@ -80,6 +102,7 @@ type APIContext ph
|
||||||
{ accessToken : String
|
{ accessToken : String
|
||||||
, baseUrl : String
|
, baseUrl : String
|
||||||
, context : Context
|
, context : Context
|
||||||
|
, now : Timestamp
|
||||||
, transaction : String
|
, transaction : String
|
||||||
, versions : Versions
|
, versions : Versions
|
||||||
}
|
}
|
||||||
|
@ -94,9 +117,11 @@ type alias Versions =
|
||||||
apiFormat : Context -> APIContext {}
|
apiFormat : Context -> APIContext {}
|
||||||
apiFormat context =
|
apiFormat context =
|
||||||
APIContext
|
APIContext
|
||||||
{ accessToken = context.accessToken |> Maybe.withDefault L.accessToken
|
{ accessToken =
|
||||||
|
mostPopularToken context |> Maybe.withDefault L.accessToken
|
||||||
, baseUrl = context.baseUrl |> Maybe.withDefault L.baseUrl
|
, baseUrl = context.baseUrl |> Maybe.withDefault L.baseUrl
|
||||||
, context = context
|
, context = context
|
||||||
|
, now = context.now |> Maybe.withDefault (Time.millisToPosix 0)
|
||||||
, transaction = context.transaction |> Maybe.withDefault L.transaction
|
, transaction = context.transaction |> Maybe.withDefault L.transaction
|
||||||
, versions = context.versions |> Maybe.withDefault L.versions
|
, versions = context.versions |> Maybe.withDefault L.versions
|
||||||
}
|
}
|
||||||
|
@ -114,16 +139,16 @@ fromApiFormat (APIContext c) =
|
||||||
-}
|
-}
|
||||||
coder : Json.Coder Context
|
coder : Json.Coder Context
|
||||||
coder =
|
coder =
|
||||||
Json.object8
|
Json.object9
|
||||||
{ name = Text.docs.context.name
|
{ name = Text.docs.context.name
|
||||||
, description = Text.docs.context.description
|
, description = Text.docs.context.description
|
||||||
, init = Context
|
, init = Context
|
||||||
}
|
}
|
||||||
(Json.field.optional.value
|
(Json.field.required
|
||||||
{ fieldName = "accessToken"
|
{ fieldName = "accessTokens"
|
||||||
, toField = .accessToken
|
, toField = .accessTokens
|
||||||
, description = Text.fields.context.accessToken
|
, description = Text.fields.context.accessToken
|
||||||
, coder = Json.string
|
, coder = Hashdict.coder .value coderAccessToken
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
(Json.field.optional.value
|
(Json.field.optional.value
|
||||||
|
@ -133,6 +158,13 @@ coder =
|
||||||
, coder = Json.string
|
, coder = Json.string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
(Json.field.optional.value
|
||||||
|
{ fieldName = "now"
|
||||||
|
, toField = .now
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, coder = Timestamp.coder
|
||||||
|
}
|
||||||
|
)
|
||||||
(Json.field.optional.value
|
(Json.field.optional.value
|
||||||
{ fieldName = "password"
|
{ fieldName = "password"
|
||||||
, toField = .password
|
, toField = .password
|
||||||
|
@ -177,6 +209,52 @@ coder =
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
{-| JSON coder for an Access Token.
|
||||||
|
-}
|
||||||
|
coderAccessToken : Json.Coder AccessToken
|
||||||
|
coderAccessToken =
|
||||||
|
Json.object5
|
||||||
|
{ name = Debug.todo "Needs docs"
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, init = AccessToken
|
||||||
|
}
|
||||||
|
(Json.field.required
|
||||||
|
{ fieldName = "created"
|
||||||
|
, toField = .created
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, coder = Timestamp.coder
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(Json.field.optional.value
|
||||||
|
{ fieldName = "expiryMs"
|
||||||
|
, toField = .expiryMs
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, coder = Json.int
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(Json.field.required
|
||||||
|
{ fieldName = "lastUsed"
|
||||||
|
, toField = .lastUsed
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, coder = Timestamp.coder
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(Json.field.optional.value
|
||||||
|
{ fieldName = "refresh"
|
||||||
|
, toField = .refresh
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, coder = Json.string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(Json.field.required
|
||||||
|
{ fieldName = "value"
|
||||||
|
, toField = .value
|
||||||
|
, description = Debug.todo "Needs docs"
|
||||||
|
, coder = Json.string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
{-| Decode a Context type from a JSON value.
|
{-| Decode a Context type from a JSON value.
|
||||||
-}
|
-}
|
||||||
decoder : Json.Decoder Context
|
decoder : Json.Decoder Context
|
||||||
|
@ -195,8 +273,9 @@ encode =
|
||||||
-}
|
-}
|
||||||
init : String -> Context
|
init : String -> Context
|
||||||
init sn =
|
init sn =
|
||||||
{ accessToken = Nothing
|
{ accessTokens = Hashdict.empty .value
|
||||||
, baseUrl = Nothing
|
, baseUrl = Nothing
|
||||||
|
, now = Nothing
|
||||||
, refreshToken = Nothing
|
, refreshToken = Nothing
|
||||||
, password = Nothing
|
, password = Nothing
|
||||||
, serverName = sn
|
, serverName = sn
|
||||||
|
@ -206,6 +285,29 @@ init sn =
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Get the most popular access token available, if any.
|
||||||
|
-}
|
||||||
|
mostPopularToken : Context -> Maybe String
|
||||||
|
mostPopularToken c =
|
||||||
|
c.accessTokens
|
||||||
|
|> Hashdict.values
|
||||||
|
|> List.sortBy
|
||||||
|
(\token ->
|
||||||
|
case token.expiryMs of
|
||||||
|
Nothing ->
|
||||||
|
( 0, Timestamp.toMs token.created )
|
||||||
|
|
||||||
|
Just e ->
|
||||||
|
( 1
|
||||||
|
, token.created
|
||||||
|
|> Timestamp.add e
|
||||||
|
|> Timestamp.toMs
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|> List.head
|
||||||
|
|> Maybe.map .value
|
||||||
|
|
||||||
|
|
||||||
{-| Get an inserted access token.
|
{-| Get an inserted access token.
|
||||||
-}
|
-}
|
||||||
getAccessToken : APIContext { a | accessToken : () } -> String
|
getAccessToken : APIContext { a | accessToken : () } -> String
|
||||||
|
@ -234,6 +336,20 @@ setBaseUrl value (APIContext c) =
|
||||||
APIContext { c | baseUrl = value }
|
APIContext { c | baseUrl = value }
|
||||||
|
|
||||||
|
|
||||||
|
{-| Get an inserted timestamp.
|
||||||
|
-}
|
||||||
|
getNow : APIContext { a | now : () } -> Timestamp
|
||||||
|
getNow (APIContext c) =
|
||||||
|
c.now
|
||||||
|
|
||||||
|
|
||||||
|
{-| Insert a Timestamp into the APIContext.
|
||||||
|
-}
|
||||||
|
setNow : Timestamp -> APIContext a -> APIContext { a | now : () }
|
||||||
|
setNow t (APIContext c) =
|
||||||
|
APIContext { c | now = t }
|
||||||
|
|
||||||
|
|
||||||
{-| Get an inserted transaction id.
|
{-| Get an inserted transaction id.
|
||||||
-}
|
-}
|
||||||
getTransaction : APIContext { a | transaction : () } -> String
|
getTransaction : APIContext { a | transaction : () } -> String
|
||||||
|
|
|
@ -51,8 +51,9 @@ settings that can be adjusted manually.
|
||||||
import Internal.Api.Request as Request
|
import Internal.Api.Request as Request
|
||||||
import Internal.Config.Log exposing (Log)
|
import Internal.Config.Log exposing (Log)
|
||||||
import Internal.Config.Text as Text
|
import Internal.Config.Text as Text
|
||||||
|
import Internal.Tools.Hashdict as Hashdict
|
||||||
import Internal.Tools.Json as Json
|
import Internal.Tools.Json as Json
|
||||||
import Internal.Values.Context as Context exposing (Context, Versions)
|
import Internal.Values.Context as Context exposing (AccessToken, Context, Versions)
|
||||||
import Internal.Values.Settings as Settings
|
import Internal.Values.Settings as Settings
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +75,8 @@ type EnvelopeUpdate a
|
||||||
= ContentUpdate a
|
= ContentUpdate a
|
||||||
| HttpRequest (Request.Request ( Request.Error, List Log ) ( EnvelopeUpdate a, List Log ))
|
| HttpRequest (Request.Request ( Request.Error, List Log ) ( EnvelopeUpdate a, List Log ))
|
||||||
| More (List (EnvelopeUpdate a))
|
| More (List (EnvelopeUpdate a))
|
||||||
| SetAccessToken String
|
| RemoveAccessToken String
|
||||||
|
| SetAccessToken AccessToken
|
||||||
| SetBaseUrl String
|
| SetBaseUrl String
|
||||||
| SetRefreshToken String
|
| SetRefreshToken String
|
||||||
| SetVersions Versions
|
| SetVersions Versions
|
||||||
|
@ -179,10 +181,10 @@ getContent =
|
||||||
{-| Create a new enveloped data type. All settings are set to default values
|
{-| Create a new enveloped data type. All settings are set to default values
|
||||||
from the [Internal.Config.Default](Internal-Config-Default) module.
|
from the [Internal.Config.Default](Internal-Config-Default) module.
|
||||||
-}
|
-}
|
||||||
init : a -> Envelope a
|
init : { serverName : String, content : a } -> Envelope a
|
||||||
init x =
|
init data =
|
||||||
{ content = x
|
{ content = data.content
|
||||||
, context = Context.init
|
, context = Context.init data.serverName
|
||||||
, settings = Settings.init
|
, settings = Settings.init
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +298,11 @@ update updateContent eu ({ context } as data) =
|
||||||
More items ->
|
More items ->
|
||||||
List.foldl (update updateContent) data items
|
List.foldl (update updateContent) data items
|
||||||
|
|
||||||
|
RemoveAccessToken token ->
|
||||||
|
{ data | context = { context | accessTokens = Hashdict.removeKey token context.accessTokens } }
|
||||||
|
|
||||||
SetAccessToken a ->
|
SetAccessToken a ->
|
||||||
{ data | context = { context | accessToken = Just a } }
|
{ data | context = { context | accessTokens = Hashdict.insert a context.accessTokens } }
|
||||||
|
|
||||||
SetBaseUrl b ->
|
SetBaseUrl b ->
|
||||||
{ data | context = { context | baseUrl = Just b } }
|
{ data | context = { context | baseUrl = Just b } }
|
||||||
|
|
Loading…
Reference in New Issue