summaryrefslogtreecommitdiff
path: root/main/State.hs
blob: 76441df2453502045393b88cd365151c64d0157b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
module State (
    loadLocalStateHead,
    updateSharedIdentity,
    interactiveIdentityUpdate,
) where

import Control.Monad.Except
import Control.Monad.IO.Class

import Data.Foldable
import Data.Maybe
import Data.Proxy
import Data.Text qualified as T

import Erebos.Error
import Erebos.Identity
import Erebos.PubKey
import Erebos.State
import Erebos.Storable
import Erebos.Storage

import Terminal


loadLocalStateHead :: MonadIO m => Terminal -> Storage -> m (Head LocalState)
loadLocalStateHead term st = loadHeads st >>= \case
    (h:_) -> return h
    [] -> liftIO $ do
        setPrompt term "Name: "
        name <- getInputLine term $ KeepPrompt . maybe T.empty T.pack

        setPrompt term "Device: "
        devName <- getInputLine term $ KeepPrompt . maybe T.empty T.pack

        owner <- if
            | T.null name -> return Nothing
            | otherwise -> Just <$> createIdentity st (Just name) Nothing

        identity <- createIdentity st (if T.null devName then Nothing else Just devName) owner

        shared <- wrappedStore st $ SharedState
            { ssPrev = []
            , ssType = Just $ sharedTypeID @(Maybe ComposedIdentity) Proxy
            , ssValue = [ storedRef $ idExtData $ fromMaybe identity owner ]
            }
        storeHead st $ LocalState
            { lsIdentity = idExtData identity
            , lsShared = [ shared ]
            , lsOther = []
            }


updateSharedIdentity :: (MonadHead LocalState m, MonadError e m, FromErebosError e) => Terminal -> m ()
updateSharedIdentity term = updateLocalHead_ $ updateSharedState_ $ \case
    Just identity -> do
        Just . toComposedIdentity <$> interactiveIdentityUpdate term identity
    Nothing -> throwOtherError "no existing shared identity"

interactiveIdentityUpdate :: (Foldable f, MonadStorage m, MonadIO m, MonadError e m, FromErebosError e) => Terminal -> Identity f -> m UnifiedIdentity
interactiveIdentityUpdate term identity = do
    let public = idKeyIdentity identity

    name <- liftIO $ do
        setPrompt term $ T.unpack $ T.concat $ concat
            [ [ T.pack "Name" ]
            , case idName identity of
                   Just name -> [T.pack " [", name, T.pack "]"]
                   Nothing -> []
            , [ T.pack ": " ]
            ]
        getInputLine term $ KeepPrompt . maybe T.empty T.pack

    if  | T.null name -> mergeIdentity identity
        | otherwise -> do
            secret <- loadKey public
            maybe (throwOtherError "created invalid identity") return . validateIdentity =<<
                mstore =<< sign secret =<< mstore (emptyIdentityData public)
                { iddPrev = toList $ idDataF identity
                , iddName = Just name
                }