Update login for all spec versions

The currently officially supported/legacy spec versions, at least.
pull/1/head
Bram van den Heuvel 2023-03-19 16:45:56 +01:00
parent 5dfd95196b
commit e0086daa59
23 changed files with 827 additions and 182 deletions

View File

@ -219,7 +219,13 @@ def main(in_file, out_file):
@property
def encoder(self):
if self.required or self.default is not None:
if self.required == 'never':
return 'Nothing'
elif self.required == 'now':
return (
'Maybe.map ' + encapsulate(self.field.encoder) + ' data.' + self.elm_name
)
elif self.required or self.default is not None:
return (
'Just <| ' + self.field.encoder + ' data.' + self.elm_name
)
@ -232,7 +238,11 @@ def main(in_file, out_file):
@property
def decoder(self):
if self.required:
if self.required == 'never':
return 'D.succeed Nothing'
elif self.required == 'now':
field = f'D.map Just <| D.field "{self.key}"'
elif self.required:
field = f'D.field "{self.key}"'
elif self.default is None:
field = f'opField "{self.key}"'
@ -243,7 +253,9 @@ def main(in_file, out_file):
@property
def type_definition(self):
if self.required or self.default is not None:
if self.required in ['now', 'never']:
return 'Maybe ' + encapsulate(self.field.type_name)
elif self.required or self.default is not None:
return self.field.type_name
else:
return 'Maybe ' + encapsulate(self.field.type_name)
@ -333,7 +345,7 @@ def main(in_file, out_file):
if 'opField ' in content and 'opFieldWithDefault ' in content:
write("import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault)\n")
elif 'opFieldWithDefault ' in content:
write("import Internal.Tools.DecodeExtra exposing (opField)\n")
write("import Internal.Tools.DecodeExtra exposing (opFieldWithDefault)\n")
elif 'opField ' in content:
write("import Internal.Tools.DecodeExtra exposing (opField)\n")

View File

@ -1,6 +1,10 @@
module Internal.Api.LoginWithUsernameAndPassword.Api exposing (..)
import Internal.Api.LoginWithUsernameAndPassword.V1.Login as SO
import Internal.Api.LoginWithUsernameAndPassword.V1.Login as SO1
import Internal.Api.LoginWithUsernameAndPassword.V2.SpecObjects as SO2
import Internal.Api.LoginWithUsernameAndPassword.V3.SpecObjects as SO3
import Internal.Api.LoginWithUsernameAndPassword.V4.SpecObjects as SO4
import Internal.Api.LoginWithUsernameAndPassword.V5.Login as SO5
import Internal.Api.Request as R
import Internal.Tools.Context exposing (Context)
import Internal.Tools.Exceptions as X
@ -14,20 +18,138 @@ type alias LoginWithUsernameAndPasswordInputV1 =
}
type alias LoginWithUsernameAndPasswordInputV2 =
{ deviceId : Maybe String
, initialDeviceDisplayName : Maybe String
, password : String
, username : String
}
type alias LoginWithUsernameAndPasswordOutputV1 =
SO.LoggedInResponse
SO1.LoggedInResponse
type alias LoginWithUsernameAndPasswordOutputV2 =
SO2.LoggedInResponse
type alias LoginWithUsernameAndPasswordOutputV3 =
SO3.LoggedInResponse
type alias LoginWithUsernameAndPasswordOutputV4 =
SO4.LoggedInResponse
type alias LoginWithUsernameAndPasswordOutputV5 =
SO5.LoggedInResponse
loginWithUsernameAndPasswordV1 : LoginWithUsernameAndPasswordInputV1 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV1
loginWithUsernameAndPasswordV1 { username, password } =
R.callApi "POST" "/_matrix/client/v3/login"
R.callApi "POST" "/_matrix/client/r0/login"
>> R.withAttributes
[ [ ( "type", E.string "m.id.user" )
[ R.bodyString "password" password
, R.bodyString "type" "m.login.password"
, R.bodyString "user" username
]
>> R.toTask SO1.loggedInResponseDecoder
loginWithUsernameAndPasswordV2 : LoginWithUsernameAndPasswordInputV2 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV2
loginWithUsernameAndPasswordV2 { deviceId, initialDeviceDisplayName, password, username } =
R.callApi "POST" "/_matrix/client/r0/login"
>> R.withAttributes
[ R.bodyString "type" "m.login.password"
, R.bodyString "user" username
, R.bodyString "password" password
, R.bodyOpString "device_id" deviceId
, R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
]
>> R.toTask SO2.loggedInResponseDecoder
loginWithUsernameAndPasswordV3 : LoginWithUsernameAndPasswordInputV2 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV3
loginWithUsernameAndPasswordV3 { deviceId, initialDeviceDisplayName, password, username } =
R.callApi "POST" "/_matrix/client/r0/login"
>> R.withAttributes
[ R.bodyString "type" "m.login.password"
, R.bodyString "password" password
, R.bodyOpString "device_id" deviceId
, R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
, [ ( "type", E.string "m.id.user" )
, ( "user", E.string username )
]
|> E.object
|> R.bodyValue "identifier"
, R.bodyString "password" password
, R.bodyString "type" "m.login.password"
]
>> R.toTask SO.loggedInResponseDecoder
>> R.toTask SO3.loggedInResponseDecoder
loginWithUsernameAndPasswordV4 : LoginWithUsernameAndPasswordInputV2 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV4
loginWithUsernameAndPasswordV4 { deviceId, initialDeviceDisplayName, password, username } =
R.callApi "POST" "/_matrix/client/r0/login"
>> R.withAttributes
[ R.bodyString "type" "m.login.password"
, R.bodyString "password" password
, R.bodyOpString "device_id" deviceId
, R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
, [ ( "type", E.string "m.id.user" )
, ( "user", E.string username )
]
|> E.object
|> R.bodyValue "identifier"
]
>> R.toTask SO4.loggedInResponseDecoder
loginWithUsernameAndPasswordV5 : LoginWithUsernameAndPasswordInputV2 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV4
loginWithUsernameAndPasswordV5 { deviceId, initialDeviceDisplayName, password, username } =
R.callApi "POST" "/_matrix/client/v3/login"
>> R.withAttributes
[ R.bodyString "type" "m.login.password"
, R.bodyString "password" password
, R.bodyOpString "device_id" deviceId
, R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
, [ ( "type", E.string "m.id.user" )
, ( "user", E.string username )
]
|> E.object
|> R.bodyValue "identifier"
]
>> R.toTask SO4.loggedInResponseDecoder
loginWithUsernameAndPasswordV6 : LoginWithUsernameAndPasswordInputV2 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV5
loginWithUsernameAndPasswordV6 { deviceId, initialDeviceDisplayName, password, username } =
R.callApi "POST" "/_matrix/client/v3/login"
>> R.withAttributes
[ R.bodyString "type" "m.login.password"
, R.bodyString "password" password
, R.bodyOpString "device_id" deviceId
, R.bodyOpString "initial_device_display_name" initialDeviceDisplayName
, R.bodyBool "refresh_token" True
, [ ( "type", E.string "m.id.user" )
, ( "user", E.string username )
]
|> E.object
|> R.bodyValue "identifier"
]
>> R.toTask SO5.loggedInResponseDecoder
-- loginWithUsernameAndPasswordV5 : LoginWithUsernameAndPasswordInputV1 -> Context { a | baseUrl : () } -> Task X.Error LoginWithUsernameAndPasswordOutputV5
-- loginWithUsernameAndPasswordV5 { username, password } =
-- R.callApi "POST" "/_matrix/client/v3/login"
-- >> R.withAttributes
-- [ [ ( "type", E.string "m.id.user" )
-- , ( "user", E.string username )
-- ]
-- |> E.object
-- |> R.bodyValue "identifier"
-- , R.bodyString "password" password
-- , R.bodyString "type" "m.login.password"
-- ]
-- >> R.toTask SO.loggedInResponseDecoder

View File

@ -1,6 +1,10 @@
module Internal.Api.LoginWithUsernameAndPassword.Main exposing (..)
import Internal.Api.LoginWithUsernameAndPassword.Api as Api
import Internal.Api.LoginWithUsernameAndPassword.V2.Upcast as U2
import Internal.Api.LoginWithUsernameAndPassword.V3.Upcast as U3
import Internal.Api.LoginWithUsernameAndPassword.V4.Upcast as U4
import Internal.Api.LoginWithUsernameAndPassword.V5.Upcast as U5
import Internal.Tools.Context as Context exposing (Context, VB)
import Internal.Tools.Exceptions as X
import Internal.Tools.VersionControl as VC
@ -11,8 +15,54 @@ loginWithUsernameAndPassword : Context (VB a) -> LoginWithUsernameAndPasswordInp
loginWithUsernameAndPassword context input =
VC.withBottomLayer
{ current = Api.loginWithUsernameAndPasswordV1
, version = "v1.5"
, version = "r0.0.0"
}
|> VC.sameForVersion "r0.0.1"
|> VC.sameForVersion "r0.1.0"
|> VC.sameForVersion "r0.2.0"
|> VC.addMiddleLayer
{ downcast = \{ username, password } -> { username = username, password = password }
, current = Api.loginWithUsernameAndPasswordV2
, upcast =
\f c ->
Task.map U2.upcastLoggedInResponse (f c)
, version = "r0.3.0"
}
|> VC.addMiddleLayer
{ downcast = identity
, current = Api.loginWithUsernameAndPasswordV3
, upcast =
\f c ->
Task.map U3.upcastLoggedInResponse (f c)
, version = "r0.4.0"
}
|> VC.addMiddleLayer
{ downcast = identity
, current = Api.loginWithUsernameAndPasswordV4
, upcast =
\f c ->
Task.map U4.upcastLoggedInResponse (f c)
, version = "r0.5.0"
}
|> VC.sameForVersion "r0.6.0"
|> VC.sameForVersion "r0.6.1"
|> VC.addMiddleLayer
{ downcast = identity
, current = Api.loginWithUsernameAndPasswordV5
, upcast = identity
, version = "v1.1"
}
|> VC.sameForVersion "v1.2"
|> VC.addMiddleLayer
{ downcast = identity
, current = Api.loginWithUsernameAndPasswordV6
, upcast =
\f c ->
Task.map U5.upcastLoggedInResponse (f c)
, version = "v1.3"
}
|> VC.sameForVersion "v1.4"
|> VC.sameForVersion "v1.5"
|> VC.sameForVersion "v1.6"
|> VC.mostRecentFromVersionList (Context.getVersions context)
|> Maybe.withDefault (always <| always <| Task.fail X.UnsupportedSpecVersion)
@ -21,8 +71,8 @@ loginWithUsernameAndPassword context input =
type alias LoginWithUsernameAndPasswordInput =
Api.LoginWithUsernameAndPasswordInputV1
Api.LoginWithUsernameAndPasswordInputV2
type alias LoginWithUsernameAndPasswordOutput =
Api.LoginWithUsernameAndPasswordOutputV1
Api.LoginWithUsernameAndPasswordOutputV5

View File

@ -1,21 +1,12 @@
module Internal.Api.LoginWithUsernameAndPassword.V1.Login exposing
( DiscoveryInformation
, HomeserverInformation
, IdentityServerInformation
, LoggedInResponse
, discoveryInformationDecoder
, encodeDiscoveryInformation
, encodeHomeserverInformation
, encodeIdentityServerInformation
( LoggedInResponse
, encodeLoggedInResponse
, homeserverInformationDecoder
, identityServerInformationDecoder
, loggedInResponseDecoder
)
{-| Automatically generated 'Login'
Last generated at Unix time 1677859025
Last generated at Unix time 1679075857
-}
@ -25,87 +16,13 @@ import Json.Decode as D
import Json.Encode as E
{-| Information that overwrites the credential's base url and more.
-}
type alias DiscoveryInformation =
{ mHomeserver : HomeserverInformation
, mIdentityServer : Maybe IdentityServerInformation
}
encodeDiscoveryInformation : DiscoveryInformation -> E.Value
encodeDiscoveryInformation data =
maybeObject
[ ( "m.homeserver", Just <| encodeHomeserverInformation data.mHomeserver )
, ( "m.identity_server", Maybe.map encodeIdentityServerInformation data.mIdentityServer )
]
discoveryInformationDecoder : D.Decoder DiscoveryInformation
discoveryInformationDecoder =
D.map2
(\a b ->
{ mHomeserver = a, mIdentityServer = b }
)
(D.field "m.homeserver" homeserverInformationDecoder)
(opField "m.identity_server" identityServerInformationDecoder)
{-| Used by clients to discover homeserver information.
-}
type alias HomeserverInformation =
{ baseUrl : String
}
encodeHomeserverInformation : HomeserverInformation -> E.Value
encodeHomeserverInformation data =
maybeObject
[ ( "base_url", Just <| E.string data.baseUrl )
]
homeserverInformationDecoder : D.Decoder HomeserverInformation
homeserverInformationDecoder =
D.map
(\a ->
{ baseUrl = a }
)
(D.field "base_url" D.string)
{-| Used by clients to discover identity server information.
-}
type alias IdentityServerInformation =
{ baseUrl : String
}
encodeIdentityServerInformation : IdentityServerInformation -> E.Value
encodeIdentityServerInformation data =
maybeObject
[ ( "base_url", Just <| E.string data.baseUrl )
]
identityServerInformationDecoder : D.Decoder IdentityServerInformation
identityServerInformationDecoder =
D.map
(\a ->
{ baseUrl = a }
)
(D.field "base_url" D.string)
{-| Confirmation that the user has successfully logged in.
{-| Confirmation that the user successfully logged in.
-}
type alias LoggedInResponse =
{ accessToken : String
, deviceId : String
, expiresInMs : Maybe Int
, homeServer : String
, refreshToken : Maybe String
, userId : String
, wellKnown : Maybe DiscoveryInformation
}
@ -113,23 +30,19 @@ encodeLoggedInResponse : LoggedInResponse -> E.Value
encodeLoggedInResponse data =
maybeObject
[ ( "access_token", Just <| E.string data.accessToken )
, ( "device_id", Just <| E.string data.deviceId )
, ( "expires_in_ms", Maybe.map E.int data.expiresInMs )
, ( "home_server", Just <| E.string data.homeServer )
, ( "refresh_token", Maybe.map E.string data.refreshToken )
, ( "user_id", Just <| E.string data.userId )
, ( "well_known", Maybe.map encodeDiscoveryInformation data.wellKnown )
]
loggedInResponseDecoder : D.Decoder LoggedInResponse
loggedInResponseDecoder =
D.map6
(\a b c d e f ->
{ accessToken = a, deviceId = b, expiresInMs = c, refreshToken = d, userId = e, wellKnown = f }
D.map4
(\a b c d ->
{ accessToken = a, homeServer = b, refreshToken = c, userId = d }
)
(D.field "access_token" D.string)
(D.field "device_id" D.string)
(opField "expires_in_ms" D.int)
(D.field "home_server" D.string)
(opField "refresh_token" D.string)
(D.field "user_id" D.string)
(opField "well_known" discoveryInformationDecoder)

View File

@ -2,44 +2,17 @@ version: V_1
name: Login
objects:
LoggedInResponse:
description: Confirmation that the user has successfully logged in.
description: Confirmation that the user successfully logged in.
fields:
access_token:
type: string
required: true
device_id:
home_server:
type: string
required: true
expires_in_ms:
type: int
required: false
refresh_token:
type: string
required: false
user_id:
type: string
required: true
well_known:
type: DiscoveryInformation
required: false
DiscoveryInformation:
description: Information that overwrites the credential's base url and more.
fields:
m.homeserver:
type: HomeserverInformation
required: true
m.identity_server:
type: IdentityServerInformation
required: false
HomeserverInformation:
description: Used by clients to discover homeserver information.
fields:
base_url:
type: string
required: true
IdentityServerInformation:
description: Used by clients to discover identity server information.
fields:
base_url:
type: string
required: true

View File

@ -0,0 +1,50 @@
module Internal.Api.LoginWithUsernameAndPassword.V2.SpecObjects exposing
( LoggedInResponse
, encodeLoggedInResponse
, loggedInResponseDecoder
)
{-| Automatically generated 'Login'
Last generated at Unix time 1679075857
-}
import Internal.Tools.EncodeExtra exposing (maybeObject)
import Json.Decode as D
import Json.Encode as E
{-| Confirmation that the user successfully logged in.
-}
type alias LoggedInResponse =
{ accessToken : String
, deviceId : Maybe String
, homeServer : String
, refreshToken : Maybe String
, userId : String
}
encodeLoggedInResponse : LoggedInResponse -> E.Value
encodeLoggedInResponse data =
maybeObject
[ ( "access_token", Just <| E.string data.accessToken )
, ( "device_id", Maybe.map E.string data.deviceId )
, ( "home_server", Just <| E.string data.homeServer )
, ( "refresh_token", Nothing )
, ( "user_id", Just <| E.string data.userId )
]
loggedInResponseDecoder : D.Decoder LoggedInResponse
loggedInResponseDecoder =
D.map5
(\a b c d e ->
{ accessToken = a, deviceId = b, homeServer = c, refreshToken = d, userId = e }
)
(D.field "access_token" D.string)
(D.map Just <| D.field "device_id" D.string)
(D.field "home_server" D.string)
(D.succeed Nothing)
(D.field "user_id" D.string)

View File

@ -0,0 +1,21 @@
version: V_2
name: Login
objects:
LoggedInResponse:
description: Confirmation that the user successfully logged in.
fields:
access_token:
type: string
required: true
device_id:
type: string
required: now
home_server:
type: string
required: true
refresh_token:
type: string
required: never
user_id:
type: string
required: true

View File

@ -0,0 +1,14 @@
module Internal.Api.LoginWithUsernameAndPassword.V2.Upcast exposing (..)
import Internal.Api.LoginWithUsernameAndPassword.V1.Login as PO
import Internal.Api.LoginWithUsernameAndPassword.V2.SpecObjects as SO
upcastLoggedInResponse : PO.LoggedInResponse -> SO.LoggedInResponse
upcastLoggedInResponse old =
{ accessToken = old.accessToken
, deviceId = Nothing
, homeServer = old.homeServer
, refreshToken = old.refreshToken
, userId = old.userId
}

View File

@ -0,0 +1,50 @@
module Internal.Api.LoginWithUsernameAndPassword.V3.SpecObjects exposing
( LoggedInResponse
, encodeLoggedInResponse
, loggedInResponseDecoder
)
{-| Automatically generated 'Login'
Last generated at Unix time 1679075857
-}
import Internal.Tools.EncodeExtra exposing (maybeObject)
import Json.Decode as D
import Json.Encode as E
{-| Confirmation that the user successfully logged in.
-}
type alias LoggedInResponse =
{ accessToken : String
, deviceId : Maybe String
, homeServer : Maybe String
, refreshToken : Maybe String
, userId : String
}
encodeLoggedInResponse : LoggedInResponse -> E.Value
encodeLoggedInResponse data =
maybeObject
[ ( "access_token", Just <| E.string data.accessToken )
, ( "device_id", Maybe.map E.string data.deviceId )
, ( "home_server", Nothing )
, ( "refresh_token", Nothing )
, ( "user_id", Just <| E.string data.userId )
]
loggedInResponseDecoder : D.Decoder LoggedInResponse
loggedInResponseDecoder =
D.map5
(\a b c d e ->
{ accessToken = a, deviceId = b, homeServer = c, refreshToken = d, userId = e }
)
(D.field "access_token" D.string)
(D.map Just <| D.field "device_id" D.string)
(D.succeed Nothing)
(D.succeed Nothing)
(D.field "user_id" D.string)

View File

@ -0,0 +1,21 @@
version: V_3
name: Login
objects:
LoggedInResponse:
description: Confirmation that the user successfully logged in.
fields:
access_token:
type: string
required: true
device_id:
type: string
required: now
home_server:
type: string
required: never
refresh_token:
type: string
required: never
user_id:
type: string
required: true

View File

@ -0,0 +1,14 @@
module Internal.Api.LoginWithUsernameAndPassword.V3.Upcast exposing (..)
import Internal.Api.LoginWithUsernameAndPassword.V2.SpecObjects as PO
import Internal.Api.LoginWithUsernameAndPassword.V3.SpecObjects as SO
upcastLoggedInResponse : PO.LoggedInResponse -> SO.LoggedInResponse
upcastLoggedInResponse old =
{ accessToken = old.accessToken
, deviceId = Nothing
, homeServer = Just old.homeServer
, refreshToken = old.refreshToken
, userId = old.userId
}

View File

@ -0,0 +1,135 @@
module Internal.Api.LoginWithUsernameAndPassword.V4.SpecObjects exposing
( DiscoveryInformation
, HomeserverInformation
, IdentityServerInformation
, LoggedInResponse
, discoveryInformationDecoder
, encodeDiscoveryInformation
, encodeHomeserverInformation
, encodeIdentityServerInformation
, encodeLoggedInResponse
, homeserverInformationDecoder
, identityServerInformationDecoder
, loggedInResponseDecoder
)
{-| Automatically generated 'Login'
Last generated at Unix time 1679075857
-}
import Internal.Tools.DecodeExtra exposing (opField)
import Internal.Tools.EncodeExtra exposing (maybeObject)
import Json.Decode as D
import Json.Encode as E
{-| Information that overwrites the credential's base url and more.
-}
type alias DiscoveryInformation =
{ mHomeserver : HomeserverInformation
, mIdentityServer : Maybe IdentityServerInformation
}
encodeDiscoveryInformation : DiscoveryInformation -> E.Value
encodeDiscoveryInformation data =
maybeObject
[ ( "m.homeserver", Just <| encodeHomeserverInformation data.mHomeserver )
, ( "m.identity_server", Maybe.map encodeIdentityServerInformation data.mIdentityServer )
]
discoveryInformationDecoder : D.Decoder DiscoveryInformation
discoveryInformationDecoder =
D.map2
(\a b ->
{ mHomeserver = a, mIdentityServer = b }
)
(D.field "m.homeserver" homeserverInformationDecoder)
(opField "m.identity_server" identityServerInformationDecoder)
{-| Used by clients to discover homeserver information.
-}
type alias HomeserverInformation =
{ baseUrl : String
}
encodeHomeserverInformation : HomeserverInformation -> E.Value
encodeHomeserverInformation data =
maybeObject
[ ( "base_url", Just <| E.string data.baseUrl )
]
homeserverInformationDecoder : D.Decoder HomeserverInformation
homeserverInformationDecoder =
D.map
(\a ->
{ baseUrl = a }
)
(D.field "base_url" D.string)
{-| Used by clients to discover identity server information.
-}
type alias IdentityServerInformation =
{ baseUrl : String
}
encodeIdentityServerInformation : IdentityServerInformation -> E.Value
encodeIdentityServerInformation data =
maybeObject
[ ( "base_url", Just <| E.string data.baseUrl )
]
identityServerInformationDecoder : D.Decoder IdentityServerInformation
identityServerInformationDecoder =
D.map
(\a ->
{ baseUrl = a }
)
(D.field "base_url" D.string)
{-| Confirmation that the user successfully logged in.
-}
type alias LoggedInResponse =
{ accessToken : String
, deviceId : Maybe String
, homeServer : Maybe String
, refreshToken : Maybe String
, userId : String
, wellKnown : Maybe DiscoveryInformation
}
encodeLoggedInResponse : LoggedInResponse -> E.Value
encodeLoggedInResponse data =
maybeObject
[ ( "access_token", Just <| E.string data.accessToken )
, ( "device_id", Maybe.map E.string data.deviceId )
, ( "home_server", Nothing )
, ( "refresh_token", Nothing )
, ( "user_id", Just <| E.string data.userId )
, ( "well_known", Maybe.map encodeDiscoveryInformation data.wellKnown )
]
loggedInResponseDecoder : D.Decoder LoggedInResponse
loggedInResponseDecoder =
D.map6
(\a b c d e f ->
{ accessToken = a, deviceId = b, homeServer = c, refreshToken = d, userId = e, wellKnown = f }
)
(D.field "access_token" D.string)
(D.map Just <| D.field "device_id" D.string)
(D.succeed Nothing)
(D.succeed Nothing)
(D.field "user_id" D.string)
(opField "well_known" discoveryInformationDecoder)

View File

@ -0,0 +1,45 @@
version: V_3
name: Login
objects:
LoggedInResponse:
description: Confirmation that the user successfully logged in.
fields:
access_token:
type: string
required: true
device_id:
type: string
required: now
home_server:
type: string
required: never
refresh_token:
type: string
required: never
user_id:
type: string
required: true
well_known:
type: DiscoveryInformation
required: false
DiscoveryInformation:
description: Information that overwrites the credential's base url and more.
fields:
m.homeserver:
type: HomeserverInformation
required: true
m.identity_server:
type: IdentityServerInformation
required: false
HomeserverInformation:
description: Used by clients to discover homeserver information.
fields:
base_url:
type: string
required: true
IdentityServerInformation:
description: Used by clients to discover identity server information.
fields:
base_url:
type: string
required: true

View File

@ -0,0 +1,15 @@
module Internal.Api.LoginWithUsernameAndPassword.V4.Upcast exposing (..)
import Internal.Api.LoginWithUsernameAndPassword.V3.SpecObjects as PO
import Internal.Api.LoginWithUsernameAndPassword.V4.SpecObjects as SO
upcastLoggedInResponse : PO.LoggedInResponse -> SO.LoggedInResponse
upcastLoggedInResponse old =
{ accessToken = old.accessToken
, deviceId = old.deviceId
, homeServer = old.homeServer
, refreshToken = old.refreshToken
, userId = old.userId
, wellKnown = Nothing
}

View File

@ -0,0 +1,138 @@
module Internal.Api.LoginWithUsernameAndPassword.V5.Login exposing
( DiscoveryInformation
, HomeserverInformation
, IdentityServerInformation
, LoggedInResponse
, discoveryInformationDecoder
, encodeDiscoveryInformation
, encodeHomeserverInformation
, encodeIdentityServerInformation
, encodeLoggedInResponse
, homeserverInformationDecoder
, identityServerInformationDecoder
, loggedInResponseDecoder
)
{-| Automatically generated 'Login'
Last generated at Unix time 1679075857
-}
import Internal.Tools.DecodeExtra exposing (opField)
import Internal.Tools.EncodeExtra exposing (maybeObject)
import Json.Decode as D
import Json.Encode as E
{-| Information that overwrites the credential's base url and more.
-}
type alias DiscoveryInformation =
{ mHomeserver : HomeserverInformation
, mIdentityServer : Maybe IdentityServerInformation
}
encodeDiscoveryInformation : DiscoveryInformation -> E.Value
encodeDiscoveryInformation data =
maybeObject
[ ( "m.homeserver", Just <| encodeHomeserverInformation data.mHomeserver )
, ( "m.identity_server", Maybe.map encodeIdentityServerInformation data.mIdentityServer )
]
discoveryInformationDecoder : D.Decoder DiscoveryInformation
discoveryInformationDecoder =
D.map2
(\a b ->
{ mHomeserver = a, mIdentityServer = b }
)
(D.field "m.homeserver" homeserverInformationDecoder)
(opField "m.identity_server" identityServerInformationDecoder)
{-| Used by clients to discover homeserver information.
-}
type alias HomeserverInformation =
{ baseUrl : String
}
encodeHomeserverInformation : HomeserverInformation -> E.Value
encodeHomeserverInformation data =
maybeObject
[ ( "base_url", Just <| E.string data.baseUrl )
]
homeserverInformationDecoder : D.Decoder HomeserverInformation
homeserverInformationDecoder =
D.map
(\a ->
{ baseUrl = a }
)
(D.field "base_url" D.string)
{-| Used by clients to discover identity server information.
-}
type alias IdentityServerInformation =
{ baseUrl : String
}
encodeIdentityServerInformation : IdentityServerInformation -> E.Value
encodeIdentityServerInformation data =
maybeObject
[ ( "base_url", Just <| E.string data.baseUrl )
]
identityServerInformationDecoder : D.Decoder IdentityServerInformation
identityServerInformationDecoder =
D.map
(\a ->
{ baseUrl = a }
)
(D.field "base_url" D.string)
{-| Confirmation that the user has successfully logged in.
-}
type alias LoggedInResponse =
{ accessToken : String
, deviceId : Maybe String
, expiresInMs : Maybe Int
, homeServer : Maybe String
, refreshToken : Maybe String
, userId : String
, wellKnown : Maybe DiscoveryInformation
}
encodeLoggedInResponse : LoggedInResponse -> E.Value
encodeLoggedInResponse data =
maybeObject
[ ( "access_token", Just <| E.string data.accessToken )
, ( "device_id", Maybe.map E.string data.deviceId )
, ( "expires_in_ms", Maybe.map E.int data.expiresInMs )
, ( "home_server", Nothing )
, ( "refresh_token", Maybe.map E.string data.refreshToken )
, ( "user_id", Just <| E.string data.userId )
, ( "well_known", Maybe.map encodeDiscoveryInformation data.wellKnown )
]
loggedInResponseDecoder : D.Decoder LoggedInResponse
loggedInResponseDecoder =
D.map7
(\a b c d e f g ->
{ accessToken = a, deviceId = b, expiresInMs = c, homeServer = d, refreshToken = e, userId = f, wellKnown = g }
)
(D.field "access_token" D.string)
(D.map Just <| D.field "device_id" D.string)
(opField "expires_in_ms" D.int)
(D.succeed Nothing)
(opField "refresh_token" D.string)
(D.field "user_id" D.string)
(opField "well_known" discoveryInformationDecoder)

View File

@ -0,0 +1,48 @@
version: V_1
name: Login
objects:
LoggedInResponse:
description: Confirmation that the user has successfully logged in.
fields:
access_token:
type: string
required: true
device_id:
type: string
required: now
expires_in_ms:
type: int
required: false
home_server:
type: string
required: never
refresh_token:
type: string
required: false
user_id:
type: string
required: true
well_known:
type: DiscoveryInformation
required: false
DiscoveryInformation:
description: Information that overwrites the credential's base url and more.
fields:
m.homeserver:
type: HomeserverInformation
required: true
m.identity_server:
type: IdentityServerInformation
required: false
HomeserverInformation:
description: Used by clients to discover homeserver information.
fields:
base_url:
type: string
required: true
IdentityServerInformation:
description: Used by clients to discover identity server information.
fields:
base_url:
type: string
required: true

View File

@ -0,0 +1,16 @@
module Internal.Api.LoginWithUsernameAndPassword.V5.Upcast exposing (..)
import Internal.Api.LoginWithUsernameAndPassword.V4.SpecObjects as PO
import Internal.Api.LoginWithUsernameAndPassword.V5.Login as SO
upcastLoggedInResponse : PO.LoggedInResponse -> SO.LoggedInResponse
upcastLoggedInResponse old =
{ accessToken = old.accessToken
, deviceId = old.deviceId
, expiresInMs = Nothing
, homeServer = old.homeServer
, refreshToken = old.refreshToken
, userId = old.userId
, wellKnown = old.wellKnown
}

View File

@ -79,21 +79,25 @@ accessToken ctoken =
|> always
AccessToken t ->
{ contextChange = Context.setAccessToken { accessToken = t, usernameAndPassword = Nothing }
{ contextChange = Context.setAccessToken { accessToken = t, loginParts = Nothing }
, messages = []
}
|> Chain.TaskChainPiece
|> Task.succeed
|> always
UsernameAndPassword { username, password, token } ->
UsernameAndPassword { username, password, token, deviceId, initialDeviceDisplayName } ->
case token of
Just t ->
accessToken (AccessToken t)
Nothing ->
loginWithUsernameAndPassword
{ username = username, password = password }
{ username = username
, password = password
, deviceId = deviceId
, initialDeviceDisplayName = initialDeviceDisplayName
}
{-| Get an event from the API.
@ -188,7 +192,7 @@ loginWithUsernameAndPassword input =
{ contextChange =
Context.setAccessToken
{ accessToken = output.accessToken
, usernameAndPassword = Just input
, loginParts = Just input
}
, messages = [ LoggedInWithUsernameAndPassword input output ]
}

View File

@ -6,12 +6,12 @@ module Internal.Api.Versions.V1.Versions exposing
{-| Automatically generated 'Versions'
Last generated at Unix time 1677064309
Last generated at Unix time 1679075857
-}
import Dict exposing (Dict)
import Internal.Tools.DecodeExtra exposing (opField, opFieldWithDefault)
import Internal.Tools.DecodeExtra exposing (opFieldWithDefault)
import Internal.Tools.EncodeExtra exposing (maybeObject)
import Json.Decode as D
import Json.Encode as E

View File

@ -24,13 +24,17 @@ type Context a
, baseUrl : String
, sentEvent : String
, transactionId : String
, usernameAndPassword : Maybe UsernameAndPassword
, loginParts : Maybe LoginParts
, versions : List String
}
type alias UsernameAndPassword =
{ username : String, password : String }
type alias LoginParts =
{ deviceId : Maybe String
, initialDeviceDisplayName : Maybe String
, password : String
, username : String
}
type alias VB a =
@ -54,7 +58,7 @@ init =
, baseUrl = L.baseUrl
, sentEvent = L.eventId
, transactionId = L.transactionId
, usernameAndPassword = Nothing
, loginParts = Nothing
, versions = L.versions
}
@ -89,9 +93,9 @@ getTransactionId (Context { transactionId }) =
{-| Get the username and password of the user, if present.
-}
getUsernameAndPassword : Context { a | accessToken : () } -> Maybe UsernameAndPassword
getUsernameAndPassword (Context { usernameAndPassword }) =
usernameAndPassword
getLoginParts : Context { a | accessToken : () } -> Maybe LoginParts
getLoginParts (Context { loginParts }) =
loginParts
{-| Get the supported spec versions from the Context.
@ -103,9 +107,9 @@ getVersions (Context { versions }) =
{-| Insert an access token into the context.
-}
setAccessToken : { accessToken : String, usernameAndPassword : Maybe UsernameAndPassword } -> Context a -> Context { a | accessToken : () }
setAccessToken { accessToken, usernameAndPassword } (Context data) =
Context { data | accessToken = accessToken, usernameAndPassword = usernameAndPassword }
setAccessToken : { accessToken : String, loginParts : Maybe LoginParts } -> Context a -> Context { a | accessToken : () }
setAccessToken { accessToken, loginParts } (Context data) =
Context { data | accessToken = accessToken, loginParts = loginParts }
{-| Insert a base url into the context.

View File

@ -4,7 +4,13 @@ module Internal.Tools.LoginValues exposing (..)
type AccessToken
= NoAccess
| AccessToken String
| UsernameAndPassword { username : String, password : String, token : Maybe String }
| UsernameAndPassword
{ deviceId : Maybe String
, initialDeviceDisplayName : Maybe String
, password : String
, token : Maybe String
, username : String
}
defaultAccessToken : AccessToken
@ -23,6 +29,8 @@ fromUsernameAndPassword username password =
{ username = username
, password = password
, token = Nothing
, deviceId = Nothing
, initialDeviceDisplayName = Nothing
}
@ -48,37 +56,29 @@ addToken s t =
AccessToken _ ->
AccessToken s
UsernameAndPassword { username, password } ->
UsernameAndPassword data ->
UsernameAndPassword
{ username = username
, password = password
, token = Just s
}
{ data | token = Just s }
addUsernameAndPassword : { username : String, password : String } -> AccessToken -> AccessToken
addUsernameAndPassword { username, password } t =
case t of
NoAccess ->
UsernameAndPassword
{ username = username
, password = password
, token = Nothing
}
fromUsernameAndPassword username password
AccessToken a ->
UsernameAndPassword
{ username = username
, password = password
, token = Just a
, deviceId = Nothing
, initialDeviceDisplayName = Nothing
}
UsernameAndPassword { token } ->
UsernameAndPassword data ->
UsernameAndPassword
{ username = username
, password = password
, token = token
}
{ data | username = username, password = password }
removeToken : AccessToken -> AccessToken
@ -90,9 +90,6 @@ removeToken t =
AccessToken _ ->
NoAccess
UsernameAndPassword { username, password } ->
UsernameAndPassword data ->
UsernameAndPassword
{ username = username
, password = password
, token = Nothing
}
{ data | token = Nothing }

View File

@ -4,7 +4,6 @@ module Internal.Values.RoomInvite exposing (..)
-}
import Dict exposing (Dict)
import Internal.Values.Room exposing (IRoom)
import Json.Encode as E

View File

@ -1,4 +1,8 @@
module Matrix.RoomInvite exposing (RoomInvite, accept, reject, acceptWithReason, rejectWithReason)
module Matrix.RoomInvite exposing
( RoomInvite, accept, reject, acceptWithReason, rejectWithReason
, roomId
, sender, stateKey, contentType, content
)
{-| Sometimes, your user will be invited to a new room!
This module offers you a few simple handles to deal with such invites -
@ -18,7 +22,7 @@ Be careful though, anyone can invite you to any room! This means that room invit
may contain offensive, shocking or other unwanted content that the user may not
want to see.
@docs RoomInviteEvent getEvent, getAllEvents
@docs roomId, RoomInviteEvent, getEvent, getAllEvents
Once you have the event you want, you can explore it with the following functions.