on master help sign in
Got login working
commita6decec0482c4c1f25b425f8e9478c3d26193c76 authoriko <ilyakooo0@gmail.com> dateSun 24 Jul 2022, 15:38 (4 years ago) parent72797ae
18 files changed+323−103
backend/Bridge.purs+1−1 backend/Main.purs+11−8 bridge.yaml+1 bw/spago.dhall+2−1 bw/src/BW.js+21−3 bw/src/BW.purs+17−4 bw/src/BW/Logic.purs+47−15 bw/src/BW/Types.purs+79−2 el/spago.dhall+14 el/src/Control/El.purs+23 el/test/Main.purs+27 ell/spago.dhall−8 ell/src/Control/Ell.purs−31 elm.js+32−3 frontend/Bridge.elm+4−1 frontend/Main.elm+17−1 packages.dhall+26−25 spago.dhall+1
backend/Bridge.purs+1−1
@@ -15,6 +15,7 @@ import Prelude
1515newtype Cmd_Login =
1616 Cmd_Login {
1717 email :: String
18+ , password :: String
1819 , server :: String
1920 }
2021
@@ -47,4 +48,3 @@ instance decodeJsonSub :: DecodeJson Sub where
4748derive instance genericSub :: Generic Sub _
4849derive instance eqSub :: Eq Sub
4950derive instance ordSub :: Ord Sub
50−
backend/Main.purs+11−8
@@ -3,27 +3,27 @@ module Main where
33import Prelude
44
55import BW as WB
6+import BW.Logic as Logic
7+import BW.Types (Email(..), Password(..))
68import Bridge (Sub(..))
79import Bridge as Bridge
8−import Control.Promise (toAff)
9−import Data.Argonaut as A
10+import Control.Monad.Reader (runReaderT)
1011import Data.Either (Either(..))
1112import Data.Maybe (Maybe(..))
1213import Data.Nullable (null, toNullable)
1314import Effect (Effect)
14−import Effect.Aff (joinFiber, runAff, runAff_)
15+import Effect.Aff (runAff_)
1516import Effect.Console (log)
1617import Elm as Elm
1718import FFI as FFI
18−import Foreign as F
1919
2020
2121main :: Effect Unit
2222main = do
2323 app <- FFI.startElm "elm"
24− Elm.subscribe app \(Bridge.Login (Bridge.Cmd_Login {email, server})) -> do
24+ Elm.subscribe app \(Bridge.Login (Bridge.Cmd_Login {email, server, password})) -> do
2525 log $ "Got cmd"
26− bwAPI <- WB.getAPI
26+ services <- WB.getServices
2727 { base : toNullable $ Just server,
2828 webVault : null,
2929 api : null,
@@ -34,9 +34,12 @@ main = do
3434 keyConnector : null
3535 }
3636 runAff_ (\res -> case res of
37− Left _ -> log "Error"
37+ Left e -> log $ show e
3838 Right x -> log $ show x
39− ) $ toAff $ bwAPI.postPrelogin {email}
39+ ) $ runReaderT (Logic.getLogInRequestToken (Email email) (Password password)) {
40+ api: services.api,
41+ crypto : services.crypto
42+ }
4043 pure unit
4144
4245 Elm.send app Hello
bridge.yaml+1
@@ -5,3 +5,4 @@ Cmd:
55- Login:
66 email: String
77 server: String
8+ password: String
bw/spago.dhall+2−1
@@ -10,7 +10,8 @@
1010 , "maybe"
1111 , "newtype"
1212 , "prelude"
13− , "ell"
13+ , "el"
14+ , "arraybuffer-types"
1415 ]
1516, packages = ../packages.dhall
1617, sources = [ "src/**/*.purs" ]
bw/src/BW.js+21−3
@@ -10,17 +10,35 @@ import { WebCryptoFunctionService } from "../../deps/bw/libs/shared/dist/src/ser
1010import { Account } from "../../deps/bw/libs/shared/dist/src/models/domain/account";
1111
1212// import BrowserStorageService from "../../deps/bw/libs/shared/dist/src/services/browserStorage.service";
13−import { CryptoService } from "../../deps/bw/libs/shared/dist/src/abstractions/crypto.service";
13+import { CryptoService } from "../../deps/bw/libs/shared/dist/src/services/crypto.service";
14+
1415import { I18nService } from "../../deps/bw/libs/shared/dist/src/services/i18n.service";
1516import { StateService } from "../../deps/bw/libs/shared/dist/src/services/state.service";
17+import { PasswordTokenRequest } from "../../deps/bw/libs/shared/dist/src/models/request/identityToken/passwordTokenRequest";
18+import { TokenRequestTwoFactor } from "../../deps/bw/libs/common/src/models/request/identityToken/tokenRequestTwoFactor.ts";
1619
17−export function getAPI(urls) {
20+export function getServices(urls) {
1821 return function () {
1922 const bg = new MainBackground()
2023
2124 bg.environmentService.setUrls(urls)
2225
23− return bg.apiService
26+ return {
27+ api: {
28+ postPrelogin: (req) => bg.apiService.postPrelogin(req),
29+ getProfile: (req) => bg.apiService.getProfile(req),
30+ postIdentityToken: (req) => bg.apiService.postIdentityToken(
31+ new PasswordTokenRequest(
32+ email = req.email,
33+ masterPasswordHash = req.masterPasswordHash,
34+ captchaResponse = req.captchaResponse,
35+ twoFactor = new TokenRequestTwoFactor(req.twoFactor),
36+ device = req.device
37+ )
38+ )
39+ },
40+ crypto: bg.cryptoService
41+ }
2442 }
2543}
2644
bw/src/BW.purs+17−4
@@ -1,16 +1,29 @@
11module BW where
22
3+import BW.Types
34import Prelude
45
5−import BW.Types
66import Control.Promise (Promise)
7+import Data.Function.Uncurried (Fn3, Fn4)
8+import Data.Nullable (Nullable)
79import Effect (Effect)
810
9−
11+type CryptoService = {
12+ makeKey :: Fn4 Password String KDF Int (Promise SymmetricCryptoKey),
13+ hashPassword :: Fn3 Password SymmetricCryptoKey (Nullable HashPurpose) (Promise Hash)
14+}
1015
1116type ApiService = {
1217 postPrelogin :: PreloginRequest -> Promise PreloginResponse,
13− getProfile :: Unit -> Promise ProfileResponse
18+ getProfile :: Unit -> Promise ProfileResponse,
19+
20+ -- TODO: There can really be more request and response types. Maybe handle this later.
21+ postIdentityToken :: PasswordTokenRequest -> Promise IdentityTokenResponse
22+}
23+
24+type Services = {
25+ crypto :: CryptoService,
26+ api :: ApiService
1427}
1528
16−foreign import getAPI :: Urls -> Effect ApiService
29+foreign import getServices :: Urls -> Effect Services
bw/src/BW/Logic.purs+47−15
@@ -1,27 +1,59 @@
11module BW.Logic where
22
3+import BW
34import BW.Types
5+import Control.El
46import Prelude
57
6−import Control.Ell (class EllHas, Ell, l)
7−import Data.Nullable (null)
8+import Control.Promise as Promise
9+import Data.Function.Uncurried (runFn3, runFn4)
10+import Data.Maybe (Maybe(..))
11+import Data.Nullable (null, toNullable)
12+import Data.String as String
13+import Effect.Aff.Class (liftAff)
814
9−newtype Email = Email String
15+makePreloginKey ::
16+ forall r.
17+ HasL "api" ApiService r =>
18+ HasL "crypto" CryptoService r =>
19+ Email -> Password -> Al r SymmetricCryptoKey
20+makePreloginKey (Email email') (Password password) = do
21+ api :: ApiService <- l (L :: L "api")
22+ crypto <- l (L :: L "crypto")
1023
11−newtype Password = Password String
24+ let email = (String.trim >>> String.toLower) email'
1225
13−generateLogin :: forall r. EllHas (hashPassword :: String -> Ell r String) r => Email -> Password -> Ell r PasswordTokenRequest
14−generateLogin (Email email) (Password password) = do
15− _ <- l _.hashPassword ""
16− -- let token = user ++ password
17− pure $
18− { email
19− , masterPasswordHash: ""
20− , captchaResponse: ""
21− , twoFactor: {
26+ {kdf, kdfIterations} <- liftAff $ Promise.toAff $ api.postPrelogin {email}
27+ liftAff $ Promise.toAff $ runFn4 crypto.makeKey (Password password) email kdf kdfIterations
28+
29+getLogInRequestToken ::
30+ forall r.
31+ HasL "api" ApiService r =>
32+ HasL "crypto" CryptoService r =>
33+ Email -> Password -> Al r IdentityTokenResponse
34+getLogInRequestToken email password = do
35+ key <- makePreloginKey email password
36+ crypto <- l (L :: L "crypto")
37+ api :: ApiService <- l (L :: L "api")
38+
39+ _localHashedPassword <- liftAff $ Promise.toAff $
40+ runFn3 crypto.hashPassword password key (toNullable $ Just hashPurposeLocalAuthorization)
41+
42+ Hash hashedPassword <- liftAff $ Promise.toAff $ runFn3 crypto.hashPassword password key null
43+
44+ liftAff $ Promise.toAff $ api.postIdentityToken {
45+ email: email,
46+ masterPasswordHash: hashedPassword,
47+ captchaResponse: "",
48+ twoFactor: {
2249 provider: twoFactorProviderTypeEmail,
2350 token: "",
24− remember: true
51+ remember: false
52+ },
53+ device: {
54+ type: deviceTypeUnknownBrowser,
55+ name: "Temporary device name",
56+ identifier: "42",
57+ pushToken: null
2558 }
26− , device: null
2759 }
bw/src/BW/Types.purs+79−2
@@ -2,6 +2,7 @@ module BW.Types where
22
33import Prelude
44
5+import Data.ArrayBuffer.Types (ArrayBuffer)
56import Data.Date (Date)
67import Data.List (List)
78import Data.Nullable (Nullable)
@@ -188,13 +189,43 @@ type Urls = {
188189}
189190
190191type PasswordTokenRequest = {
191− email :: String,
192+ email :: Email,
192193 masterPasswordHash :: String,
193194 captchaResponse :: String,
194195 twoFactor :: TokenRequestTwoFactor,
195− device :: Nullable Unit -- we won't use this, so leave this null
196+ device :: DeviceRequest
197+}
198+
199+type DeviceRequest = {
200+ type :: DeviceType,
201+ name :: String,
202+ identifier :: String,
203+ pushToken :: Nullable String
196204}
197205
206+deviceTypeAndroid = 0 :: DeviceType
207+deviceTypeiOS = 1 :: DeviceType
208+deviceTypeChromeExtension = 2 :: DeviceType
209+deviceTypeFirefoxExtension = 3 :: DeviceType
210+deviceTypeOperaExtension = 4 :: DeviceType
211+deviceTypeEdgeExtension = 5 :: DeviceType
212+deviceTypeWindowsDesktop = 6 :: DeviceType
213+deviceTypeMacOsDesktop = 7 :: DeviceType
214+deviceTypeLinuxDesktop = 8 :: DeviceType
215+deviceTypeChromeBrowser = 9 :: DeviceType
216+deviceTypeFirefoxBrowser = 10 :: DeviceType
217+deviceTypeOperaBrowser = 11 :: DeviceType
218+deviceTypeEdgeBrowser = 12 :: DeviceType
219+deviceTypeIEBrowser = 13 :: DeviceType
220+deviceTypeUnknownBrowser = 14 :: DeviceType
221+deviceTypeAndroidAmazon = 15 :: DeviceType
222+deviceTypeUWP = 16 :: DeviceType
223+deviceTypeSafariBrowser = 17 :: DeviceType
224+deviceTypeVivaldiBrowser = 18 :: DeviceType
225+deviceTypeVivaldiExtension = 19 :: DeviceType
226+deviceTypeSafariExtension = 20 :: DeviceType
227+type DeviceType = Int
228+
198229type TokenRequestTwoFactor = {
199230 provider :: TwoFactorProviderType,
200231 token :: String,
@@ -210,3 +241,49 @@ twoFactorProviderTypeRemember = 5 :: TwoFactorProviderType
210241twoFactorProviderTypeOrganizationDuo = 6 :: TwoFactorProviderType
211242twoFactorProviderTypeWebAuthn = 7 :: TwoFactorProviderType
212243type TwoFactorProviderType = Int
244+
245+
246+type SymmetricCryptoKey = {
247+ key :: ArrayBuffer,
248+ encKey :: Nullable ArrayBuffer,
249+ macKey :: Nullable ArrayBuffer,
250+ encType :: EncryptionType,
251+ keyB64 :: String,
252+ encKeyB64 :: String,
253+ macKeyB64 :: String
254+}
255+
256+encryptionTypeAesCbc256_B64 = 0 :: EncryptionType
257+encryptionTypeAesCbc128_HmacSha256_B64 = 1 :: EncryptionType
258+encryptionTypeAesCbc256_HmacSha256_B64 = 2 :: EncryptionType
259+encryptionTypeRsa2048_OaepSha256_B64 = 3 :: EncryptionType
260+encryptionTypeRsa2048_OaepSha1_B64 = 4 :: EncryptionType
261+encryptionTypeRsa2048_OaepSha256_HmacSha256_B64 = 5 :: EncryptionType
262+encryptionTypeRsa2048_OaepSha1_HmacSha256_B64 = 6 :: EncryptionType
263+type EncryptionType = Int
264+
265+newtype Password = Password String
266+
267+hashPurposeServerAuthorization = 1 :: HashPurpose
268+hashPurposeLocalAuthorization = 2 :: HashPurpose
269+type HashPurpose = Int
270+
271+newtype Hash = Hash String
272+
273+type IdentityTokenResponse = {
274+ accessToken :: String,
275+ expiresIn :: Int,
276+ refreshToken :: String,
277+ tokenType :: String,
278+ resetMasterPassword :: Boolean,
279+ privateKey :: String,
280+ key :: String,
281+ twoFactorToken :: Nullable String,
282+ kdf :: KDF,
283+ kdfIterations :: Int,
284+ forcePasswordReset :: Nullable Boolean,
285+ apiUseKeyConnector :: Nullable Boolean,
286+ keyConnectorUrl :: Nullable String
287+}
288+
289+newtype Email = Email String
el/spago.dhallnew file+14
@@ -0,0 +1,14 @@
1+{ name = "bw"
2+, dependencies =
3+ [ "aff"
4+ , "effect"
5+ , "newtype"
6+ , "prelude"
7+ , "record"
8+ , "test-unit"
9+ , "transformers"
10+ , "unsafe-coerce"
11+ ]
12+, packages = ../packages.dhall
13+, sources = [ "src/**/*.purs", "test/**/*.purs" ]
14+}
el/src/Control/El.pursnew file+23
@@ -0,0 +1,23 @@
1+module Control.El (El, Al, l, class HasL, L(..)) where
2+
3+
4+import Control.Monad.Reader (class MonadAsk, ReaderT, asks)
5+import Data.Symbol (class IsSymbol, reflectSymbol)
6+import Effect (Effect)
7+import Effect.Aff (Aff)
8+import Prim.Row (class Cons, class Nub)
9+import Record.Unsafe (unsafeGet)
10+import Type.Proxy (Proxy(..))
11+
12+data L :: forall k. k -> Type
13+data L t = L
14+
15+type El r = ReaderT (Record r) Effect
16+type Al r = ReaderT (Record r) Aff
17+
18+l :: forall res r field m. MonadAsk (Record r) m => HasL field res r => IsSymbol field => L field -> m res
19+l L = asks (unsafeGet (reflectSymbol (Proxy :: Proxy field)))
20+
21+class HasL :: forall k1 k2 k3. k1 -> k2 -> k3 -> Constraint
22+class HasL field t r | field r -> t
23+instance (Cons field t r r', Nub r' r) => HasL field t r
el/test/Main.pursnew file+27
@@ -0,0 +1,27 @@
1+module Test.Main
2+ ( main
3+ )
4+ where
5+
6+import Prelude
7+import Test.Unit
8+
9+import Control.El
10+import Control.Monad.Reader (runReaderT)
11+import Effect (Effect)
12+import Effect.Aff (launchAff_)
13+import Test.Unit.Assert as Assert
14+import Test.Unit.Output.Fancy (runTest)
15+import Type.Proxy (Proxy(..))
16+
17+main ∷ Effect Unit
18+main = launchAff_ $ void $ runTest do
19+ suite "sync code" do
20+ test "arithmetic" do
21+ x <- runReaderT singleHandler {handle: 2, ignore: "Hello"}
22+ Assert.equal x 2
23+
24+
25+singleHandler :: forall r. HasL "handle" Int r => Al r Int
26+singleHandler = do
27+ l (L :: L "handle")
ell/spago.dhalldeleted−8
@@ -1,8 +0,0 @@
1−{ name = "bw"
2−, dependencies =
3− [ "prelude"
4− , "transformers"
5− ]
6−, packages = ../packages.dhall
7−, sources = [ "src/**/*.purs" ]
8−}
ell/src/Control/Ell.pursdeleted−31
@@ -1,31 +0,0 @@
1−module Control.Ell where
2−
3−import Prelude
4−
5−import Control.Monad.Reader (ReaderT, asks)
6−import Effect (Effect)
7−import Prim.Row (class Cons, class Union, class Nub)
8−
9−type Ell r a = ReaderT { | r } Effect a
10−
11−l :: forall r a res. ApplyEll r a res => ({ | r } -> a) -> res
12−l f = appEll (asks f)
13−
14−class EllHas row r
15−
16−instance (Union row r r', Nub r' r) => EllHas row r
17−
18−class ApplyEll r a res | r a -> res where
19− appEll :: Ell r a -> res
20−
21−instance ApplyEll r b c => ApplyEll r (a -> b) (a -> c) where
22− appEll f a = appEll ((\g -> g a) <$> f)
23−
24−else instance ApplyEll r (Ell r a) (Ell r a) where
25− appEll = join
26−
27−else instance ApplyEll r a (Ell r a) where
28− appEll = identity
29−
30−foo ∷ ∀ (t55 ∷ Type) (t56 ∷ Row Type). { foo ∷ t55 | t56 } → t55
31−foo = _.foo
elm.js+32−3
@@ -10590,7 +10590,7 @@ var $author$project$FFI$getBridge = F2(
1059010590 }
1059110591 }));
1059210592 });
10593−var $author$project$Main$init = {email: '', error: $elm$core$Maybe$Nothing, messages: _List_Nil, server: ''};
10593+var $author$project$Main$init = {email: '', error: $elm$core$Maybe$Nothing, messages: _List_Nil, password: '', server: ''};
1059410594var $author$project$Bridge$Login = function (a) {
1059510595 return {$: 'Login', a: a};
1059610596};
@@ -10603,6 +10603,9 @@ var $author$project$Bridge$jsonEncCmd_Login = function (val) {
1060310603 'email',
1060410604 $elm$json$Json$Encode$string(val.email)),
1060510605 _Utils_Tuple2(
10606+ 'password',
10607+ $elm$json$Json$Encode$string(val.password)),
10608+ _Utils_Tuple2(
1060610609 'server',
1060710610 $elm$json$Json$Encode$string(val.server))
1060810611 ]));
@@ -10650,18 +10653,28 @@ var $author$project$Main$update = F2(
1065010653 model,
1065110654 {server: server}),
1065210655 $elm$core$Platform$Cmd$none);
10656+ case 'UpdatePassword':
10657+ var password = msg.a;
10658+ return _Utils_Tuple2(
10659+ _Utils_update(
10660+ model,
10661+ {password: password}),
10662+ $elm$core$Platform$Cmd$none);
1065310663 default:
1065410664 return _Utils_Tuple2(
1065510665 model,
1065610666 $author$project$FFI$sendBridge(
1065710667 $author$project$Bridge$Login(
10658− {email: model.email, server: model.server})));
10668+ {email: model.email, password: model.password, server: model.server})));
1065910669 }
1066010670 });
1066110671var $author$project$Main$Submit = {$: 'Submit'};
1066210672var $author$project$Main$UpdateEmail = function (a) {
1066310673 return {$: 'UpdateEmail', a: a};
1066410674};
10675+var $author$project$Main$UpdatePassword = function (a) {
10676+ return {$: 'UpdatePassword', a: a};
10677+};
1066510678var $author$project$Main$UpdateServer = function (a) {
1066610679 return {$: 'UpdateServer', a: a};
1066710680};
@@ -10765,6 +10778,22 @@ var $author$project$Main$view = function (model) {
1076510778 A2(
1076610779 $elm$html$Html$h4,
1076710780 _List_Nil,
10781+ _List_fromArray(
10782+ [
10783+ $elm$html$Html$text('Password')
10784+ ])),
10785+ A2(
10786+ $elm$html$Html$input,
10787+ _List_fromArray(
10788+ [
10789+ $elm$html$Html$Attributes$type_('text'),
10790+ $elm$html$Html$Attributes$value(model.password),
10791+ $elm$html$Html$Events$onInput($author$project$Main$UpdatePassword)
10792+ ]),
10793+ _List_Nil),
10794+ A2(
10795+ $elm$html$Html$h4,
10796+ _List_Nil,
1076810797 _List_fromArray(
1076910798 [
1077010799 $elm$html$Html$text('Server')
@@ -10831,4 +10860,4 @@ var $author$project$Main$main = $elm$browser$Browser$element(
1083110860 view: $author$project$Main$view
1083210861 });
1083310862_Platform_export({'Main':{'init':$author$project$Main$main(
10834− $elm$json$Json$Decode$succeed(_Utils_Tuple0))({"versions":{"elm":"0.19.1"},"types":{"message":"Main.Msg","aliases":{},"unions":{"Main.Msg":{"args":[],"tags":{"RecieveMessage":["String.String"],"Error":["String.String"],"UpdateEmail":["String.String"],"UpdateServer":["String.String"],"Submit":[]}},"String.String":{"args":[],"tags":{"String":[]}}}}})}});}(this));
10863+ $elm$json$Json$Decode$succeed(_Utils_Tuple0))({"versions":{"elm":"0.19.1"},"types":{"message":"Main.Msg","aliases":{},"unions":{"Main.Msg":{"args":[],"tags":{"RecieveMessage":["String.String"],"Error":["String.String"],"UpdateEmail":["String.String"],"UpdateServer":["String.String"],"UpdatePassword":["String.String"],"Submit":[]}},"String.String":{"args":[],"tags":{"String":[]}}}}})}});}(this));
frontend/Bridge.elm+4−1
@@ -10,19 +10,22 @@ import Set exposing (Set)
1010
1111type alias Cmd_Login =
1212 { email: String
13+ , password: String
1314 , server: String
1415 }
1516
1617jsonDecCmd_Login : Json.Decode.Decoder ( Cmd_Login )
1718jsonDecCmd_Login =
18− Json.Decode.succeed (\pemail pserver -> {email = pemail, server = pserver})
19+ Json.Decode.succeed (\pemail ppassword pserver -> {email = pemail, password = ppassword, server = pserver})
1920 |> required "email" (Json.Decode.string)
21+ |> required "password" (Json.Decode.string)
2022 |> required "server" (Json.Decode.string)
2123
2224jsonEncCmd_Login : Cmd_Login -> Value
2325jsonEncCmd_Login val =
2426 Json.Encode.object
2527 [ ("email", Json.Encode.string val.email)
28+ , ("password", Json.Encode.string val.password)
2629 , ("server", Json.Encode.string val.server)
2730 ]
2831
frontend/Main.elm+17−1
@@ -14,6 +14,7 @@ type Msg
1414 | Error String
1515 | UpdateEmail String
1616 | UpdateServer String
17+ | UpdatePassword String
1718 | Submit
1819
1920
@@ -22,6 +23,7 @@ type alias Model =
2223 , error : Maybe String
2324 , server : String
2425 , email : String
26+ , password : String
2527 }
2628
2729
@@ -41,6 +43,7 @@ init =
4143 , error = Nothing
4244 , server = ""
4345 , email = ""
46+ , password = ""
4447 }
4548
4649
@@ -52,6 +55,8 @@ view model =
5255 , ul [] (model.messages |> List.map (text >> List.singleton >> li []))
5356 , h4 [] [ text "Email" ]
5457 , input [ Attr.type_ "text", Attr.value model.email, Ev.onInput UpdateEmail ] []
58+ , h4 [] [ text "Password" ]
59+ , input [ Attr.type_ "text", Attr.value model.password, Ev.onInput UpdatePassword ] []
5560 , h4 [] [ text "Server" ]
5661 , input [ Attr.type_ "text", Attr.value model.server, Ev.onInput UpdateServer ] []
5762 , button [ Ev.onClick Submit ] [ text "Submit" ]
@@ -80,5 +85,16 @@ update msg model =
8085 UpdateServer server ->
8186 ( { model | server = server }, Cmd.none )
8287
88+ UpdatePassword password ->
89+ ( { model | password = password }, Cmd.none )
90+
8391 Submit ->
84− ( model, FFI.sendBridge (Bridge.Login { email = model.email, server = model.server }) )
92+ ( model
93+ , FFI.sendBridge
94+ (Bridge.Login
95+ { email = model.email
96+ , server = model.server
97+ , password = model.password
98+ }
99+ )
100+ )
packages.dhall+26−25
@@ -103,28 +103,29 @@ let upstream =
103103 sha256:7a24ebdbacb2bfa27b2fc6ce3da96f048093d64e54369965a2a7b5d9892b6031
104104
105105in upstream
106− with bw = ./bw/spago.dhall as Location
107− with ell = ./ell/spago.dhall as Location
108− with argonaut-aeson-generic =
109− { dependencies =
110− [ "argonaut-codecs"
111− , "argonaut-core"
112− , "argonaut-generic"
113− , "arrays"
114− , "bifunctors"
115− , "control"
116− , "effect"
117− , "either"
118− , "foldable-traversable"
119− , "foreign-object"
120− , "maybe"
121− , "partial"
122− , "prelude"
123− , "psci-support"
124− , "record"
125− , "test-unit"
126− , "typelevel-prelude"
127− ]
128− , repo = "https://github.com/ilyakooo0/purescript-argonaut-aeson-generic.git"
129− , version = "purescript-0.14"
130− }
106+ with bw = ./bw/spago.dhall as Location
107+ with el = ./el/spago.dhall as Location
108+ with argonaut-aeson-generic =
109+ { dependencies =
110+ [ "argonaut-codecs"
111+ , "argonaut-core"
112+ , "argonaut-generic"
113+ , "arrays"
114+ , "bifunctors"
115+ , "control"
116+ , "effect"
117+ , "either"
118+ , "foldable-traversable"
119+ , "foreign-object"
120+ , "maybe"
121+ , "partial"
122+ , "prelude"
123+ , "psci-support"
124+ , "record"
125+ , "test-unit"
126+ , "typelevel-prelude"
127+ ]
128+ , repo =
129+ "https://github.com/ilyakooo0/purescript-argonaut-aeson-generic.git"
130+ , version = "purescript-0.14"
131+ }
spago.dhall+1
@@ -26,6 +26,7 @@ to generate this file without the comments in this block.
2626 , "newtype"
2727 , "nullable"
2828 , "prelude"
29+ , "transformers"
2930 ]
3031, packages = ./packages.dhall
3132, sources = [ "backend/**/*.purs" ]