@@ -6,7 +6,7 @@ import Prelude
66
77import BW (ApiService, CryptoFunctions, Services, CryptoService)
88import BW as WB
9−import BW.Logic (bwPasswordStringHash, decodeCipher, decrypt, encodeCipher, hashPassword, liftPromise)
9+import BW.Logic (bwPasswordStringHash, decodeCipher, decrypt, encodeCipher, hashPassword, liftPromise, supportedCipher)
1010import BW.Logic as Logic
1111import BW.Types (CipherResponse, Email(..), Password(..), Urls, cipherTypeCard, cipherTypeIdentity, cipherTypeLogin, cipherTypeSecureNote, fromTwoFactorProviderType)
1212import Bridge as Bridge
@@ -16,6 +16,7 @@ import Data.Array as Array
1616import Data.Clipboard as Clipboard
1717import Data.DateTime (DateTime)
1818import Data.Either (Either(..))
19+import Data.Foldable (for_)
1920import Data.HCaptcha (bindHCaptchToken)
2021import Data.JNullable (jnull, nullify)
2122import Data.JNullable as JNullable
@@ -61,19 +62,19 @@ main = do
6162 let
6263 runAff act = runElmAff app $ run $ act
6364
64− run ::
65− forall a.
66− Run
67− ( app :: Reader Elm
68− , aff :: Aff
69− , effect :: Effect
70− , crypto :: Reader CryptoService
71− , storage :: Reader Storage
72− , services :: Reader Services
73− , cryptoFunctions :: Reader CryptoFunctions
74− )
75− a ->
76− Run (EFFECT + AFF + ()) a
65+ run
66+ :: forall a
67+ . Run
68+ ( app :: Reader Elm
69+ , aff :: Aff
70+ , effect :: Effect
71+ , crypto :: Reader CryptoService
72+ , storage :: Reader Storage
73+ , services :: Reader Services
74+ , cryptoFunctions :: Reader CryptoFunctions
75+ )
76+ a
77+ -> Run (EFFECT + AFF + ()) a
7778 run act =
7879 runReaderAt (Proxy :: _ "app") app
7980 $ runReaderAt (Proxy :: _ "crypto") services.crypto
@@ -82,19 +83,19 @@ main = do
8283 $ runReaderAt (Proxy :: _ "cryptoFunctions") services.cryptoFunctions
8384 $ act
8485
85− runWithDecryptionKey ::
86− Run
87− ( app :: Reader Elm
88− , aff :: Aff
89− , effect :: Effect
90− , key :: Reader SymmetricCryptoKey
91− , crypto :: Reader CryptoService
92− , storage :: Reader Storage
93− , services :: Reader Services
94− , cryptoFunctions :: Reader CryptoFunctions
95− )
96− Unit ->
97− Effect Unit
86+ runWithDecryptionKey
87+ :: Run
88+ ( app :: Reader Elm
89+ , aff :: Aff
90+ , effect :: Effect
91+ , key :: Reader SymmetricCryptoKey
92+ , crypto :: Reader CryptoService
93+ , storage :: Reader Storage
94+ , services :: Reader Services
95+ , cryptoFunctions :: Reader CryptoFunctions
96+ )
97+ Unit
98+ -> Effect Unit
9899 runWithDecryptionKey act = do
99100 maybeKey <- Ref.read masterKeyRef
100101 runAff
@@ -182,9 +183,9 @@ main = do
182183 Bridge.Init -> do
183184 Storage.get storage TokenKey
184185 >>= \x ->
185− Elm.send app case x of
186− Just _ -> Bridge.LoginSuccessful
187− Nothing -> Bridge.NeedsLogin
186+ Elm.send app case x of
187+ Just _ -> Bridge.LoginSuccessful
188+ Nothing -> Bridge.NeedsLogin
188189 Bridge.RequestCipher id ->
189190 runWithDecryptionKey do
190191 sync <- getOrReset SyncKey
@@ -192,8 +193,7 @@ main = do
192193 Nothing -> pure unit
193194 Just cipherResponse -> do
194195 cipher <- decodeCipher cipherResponse
195− send $ Bridge.LoadCipher cipher
196− pure unit
196+ for_ cipher $ send <<< Bridge.LoadCipher
197197 pure unit
198198 Bridge.NeedEmail ->
199199 runWithDecryptionKey do
@@ -209,7 +209,7 @@ main = do
209209 api <- getAuthedApi
210210 cipher <- encodeCipher fullCipher
211211 newCipher <- liftPromise (api.putCipher cipher) >>= decodeCipher
212− send $ Bridge.CipherChanged newCipher
212+ for_ newCipher $ send <<< Bridge.CipherChanged
213213 performSync
214214 pure unit
215215 Bridge.GeneratePassword cfg ->
@@ -222,7 +222,7 @@ main = do
222222 api <- getAuthedApi
223223 cipher <- encodeCipher fullCipher
224224 newCipher <- liftPromise (api.postCipherCreate cipher) >>= decodeCipher
225− send $ Bridge.CipherChanged newCipher
225+ for_ newCipher $ send <<< Bridge.CipherChanged
226226 performSync
227227 pure unit
228228 Bridge.DeleteCipher c@(Bridge.FullCipher { id }) ->
@@ -240,14 +240,20 @@ main = do
240240 interval = totpService.getTimeInterval totp
241241 send $ Bridge.Totp
242242 $ Bridge.Sub_Totp
243− { interval, code, source: totp
243+ { interval
244+ , code
245+ , source: totp
244246 }
245247 pure unit
246248 Bridge.ChooseSecondFactor
247249 ( Bridge.Cmd_ChooseSecondFactor
248− { email: email', factor, server, password, requestFromServer
249− }
250− ) ->
250+ { email: email'
251+ , factor
252+ , server
253+ , password
254+ , requestFromServer
255+ }
256+ ) ->
251257 when requestFromServer
252258 let
253259 email = Email email'
@@ -264,17 +270,18 @@ main = do
264270 pure unit
265271 _ -> pure unit
266272
267−processCipher ::
268− forall r.
269− CipherResponse ->
270− Run
271− ( crypto :: Reader CryptoService
272− , key :: Reader SymmetricCryptoKey
273− , aff :: Aff
274− , effect :: Effect
275− | r
276− )
277− { cipher :: Bridge.Sub_LoadCiphers, date :: DateTime }
273+processCipher
274+ :: forall r
275+ . CipherResponse
276+ -> Run
277+ ( crypto :: Reader CryptoService
278+ , key :: Reader SymmetricCryptoKey
279+ , aff :: Aff
280+ , effect :: Effect
281+ | r
282+ )
283+ (Maybe { cipher :: Bridge.Sub_LoadCiphers, date :: DateTime })
284+processCipher cipher | not (supportedCipher cipher) = pure Nothing
278285processCipher cipher = do
279286 name <- decrypt cipher.name
280287 cipherType <- case cipher.type of
@@ -289,7 +296,9 @@ processCipher cipher = do
289296 n -> liftEffect $ throw $ "Unsupported cipher type: " <> show n
290297 date <- liftEffect $ maybe (pure bottom) (Timestamp.toDateTime) $ JNullable.toMaybe cipher.revisionDate
291298 pure
292− $ { cipher:
299+ $ Just
300+ $
301+ { cipher:
293302 Bridge.Sub_LoadCiphers
294303 { name: name
295304 , date: maybe "" Timestamp.toLocalDateTimeString $ JNullable.toMaybe cipher.revisionDate
@@ -323,18 +332,18 @@ baseUrl server =
323332 , keyConnector: jnull
324333 }
325334
326−getOrReset ::
327− forall k t r.
328− StorageKey k t =>
329− DecodeJson t =>
330− k ->
331− Run
332− ( storage :: Reader Storage
333− , app :: Reader Elm
334− , effect :: Effect
335− | r
336− )
337− t
335+getOrReset
336+ :: forall k t r
337+ . StorageKey k t
338+ => DecodeJson t
339+ => k
340+ -> Run
341+ ( storage :: Reader Storage
342+ , app :: Reader Elm
343+ , effect :: Effect
344+ | r
345+ )
346+ t
338347getOrReset key = do
339348 storage <- askAt (Proxy :: _ "storage")
340349 app <- askAt (Proxy :: _ "app")
@@ -345,69 +354,69 @@ getOrReset key = do
345354 Exc.throw "Encountered an internal error. Resetting the app."
346355 liftEffect $ try (Storage.get storage key)
347356 >>= \x -> case x of
348− Left err -> do
349− log $ show err
350− handleError
351− Right Nothing -> handleError
352− Right (Just y) -> pure y
357+ Left err -> do
358+ log $ show err
359+ handleError
360+ Right Nothing -> handleError
361+ Right (Just y) -> pure y
353362
354−getAuthedApi ::
355− forall r.
356− Run
357− ( storage :: Reader Storage
358− , app :: Reader Elm
359− , aff :: Aff
360− , effect :: Effect
361− , services :: Reader Services
362− | r
363− )
364− ApiService
363+getAuthedApi
364+ :: forall r
365+ . Run
366+ ( storage :: Reader Storage
367+ , app :: Reader Elm
368+ , aff :: Aff
369+ , effect :: Effect
370+ , services :: Reader Services
371+ | r
372+ )
373+ ApiService
365374getAuthedApi = do
366375 services <- askAt (Proxy :: _ "services")
367376 token <- getOrReset TokenKey
368377 url <- getOrReset UrlsKey
369378 liftPromise $ services.getApi (baseUrl url) (nullify token)
370379
371−requestMasterPassword ::
372− forall r.
373− Run
374− ( storage :: Reader Storage
375− , app :: Reader Elm
376− , effect :: Effect
377− | r
378− )
379− Unit
380+requestMasterPassword
381+ :: forall r
382+ . Run
383+ ( storage :: Reader Storage
384+ , app :: Reader Elm
385+ , effect :: Effect
386+ | r
387+ )
388+ Unit
380389requestMasterPassword = do
381390 url <- getOrReset UrlsKey
382391 sync <- getOrReset SyncKey
383392 send $ Bridge.NeedsMasterPassword $ Bridge.Sub_NeedsMasterPassword { server: url, login: sync.profile.email }
384393
385−send ::
386− forall r.
387− Bridge.Sub ->
388− Run
389− ( app :: Reader Elm
390− , effect :: Effect
391− | r
392− )
393− Unit
394+send
395+ :: forall r
396+ . Bridge.Sub
397+ -> Run
398+ ( app :: Reader Elm
399+ , effect :: Effect
400+ | r
401+ )
402+ Unit
394403send sub = do
395404 app <- askAt (Proxy :: _ "app")
396405 liftEffect $ Elm.send app sub
397406
398−performSync ::
399− forall r.
400− Run
401− ( storage :: Reader Storage
402− , app :: Reader Elm
403− , aff :: Aff
404− , effect :: Effect
405− , services :: Reader Services
406− , crypto :: Reader CryptoService
407− , key :: Reader SymmetricCryptoKey
408− | r
409− )
410− Unit
407+performSync
408+ :: forall r
409+ . Run
410+ ( storage :: Reader Storage
411+ , app :: Reader Elm
412+ , aff :: Aff
413+ , effect :: Effect
414+ , services :: Reader Services
415+ , crypto :: Reader CryptoService
416+ , key :: Reader SymmetricCryptoKey
417+ | r
418+ )
419+ Unit
411420performSync = do
412421 api <- getAuthedApi
413422 storage <- askAt (Proxy :: _ "storage")
@@ -415,22 +424,22 @@ performSync = do
415424 liftEffect $ Storage.store storage SyncKey newSync
416425 sendCiphers
417426
418−sendCiphers ::
419− forall r.
420− Run
421− ( storage :: Reader Storage
422− , app :: Reader Elm
423− , aff :: Aff
424− , effect :: Effect
425− , services :: Reader Services
426− , crypto :: Reader CryptoService
427− , key :: Reader SymmetricCryptoKey
428− | r
429− )
430− Unit
427+sendCiphers
428+ :: forall r
429+ . Run
430+ ( storage :: Reader Storage
431+ , app :: Reader Elm
432+ , aff :: Aff
433+ , effect :: Effect
434+ , services :: Reader Services
435+ , crypto :: Reader CryptoService
436+ , key :: Reader SymmetricCryptoKey
437+ | r
438+ )
439+ Unit
431440sendCiphers = do
432441 sync <- getOrReset SyncKey
433− ciphers <- traverse processCipher sync.ciphers
442+ ciphers <- Array.catMaybes <$> traverse processCipher sync.ciphers
434443 let
435444 sortedCiphers = Array.sortWith (_.date >>> Down) ciphers
436445 send $ Bridge.LoadCiphers $ Bridge.Sub_LoadCiphers_List $ map _.cipher sortedCiphers