diff --git a/src/Apps/Browser/Config.elm b/src/Apps/Browser/Config.elm index 416d4ef9..cccca88c 100644 --- a/src/Apps/Browser/Config.elm +++ b/src/Apps/Browser/Config.elm @@ -6,11 +6,11 @@ import Core.Flags as Core import Utils.Core exposing (..) import Apps.Params as AppParams exposing (AppParams) import Game.Account.Database.Models exposing (HackedServers) -import Game.Account.Finances.Requests.Login as LoginRequest -import Game.Account.Finances.Requests.Transfer as TransferRequest +import Game.Account.Finances.Models as Finances exposing (AccountNumber) +import Game.Bank.Models as Bank import Game.Meta.Types.Desktop.Apps as DesktopApp exposing (DesktopApp) import Game.Meta.Types.Context exposing (Context(..)) -import Game.Meta.Types.Network as Network exposing (NIP) +import Game.Meta.Types.Network as Network exposing (NIP, IP) import Game.Meta.Types.Desktop.Apps exposing (Reference, Requester) import Game.Servers.Models as Servers import Game.Servers.Shared as Servers exposing (CId) @@ -37,6 +37,7 @@ type alias Config msg = , activeServer : ( CId, Servers.Server ) , activeGateway : ( CId, Servers.Server ) , hackedServers : HackedServers + , bank : Bank.Model , onNewApp : DesktopApp -> Maybe Context -> Maybe AppParams -> CId -> msg , onOpenApp : AppParams -> CId -> msg , onSetContext : Context -> msg @@ -45,8 +46,14 @@ type alias Config msg = , onSetEndpoint : Maybe CId -> msg , onNewPublicDownload : NIP -> Download.StorageId -> Filesystem.FileEntry -> msg , onNewBruteforceProcess : Network.IP -> msg - , onBankAccountLogin : LoginRequest.Payload -> Requester -> msg - , onBankAccountTransfer : TransferRequest.Payload -> Requester -> msg + , onBankAccountLogin : Finances.AccountId -> String -> Requester -> msg + , onBankAccountLoginToken : Finances.AccountId -> String -> Requester -> msg + , onBankAccountChangePass : String -> Requester -> msg + , onBankAccountCreate : Finances.AtmId -> Requester -> msg + , onBankAccountClose : String -> Requester -> msg + , onBankAccountLogout : String -> Requester -> msg + , onBankResync : String -> Requester -> msg + , onBankAccountTransfer : String -> IP -> AccountNumber -> Int -> Requester -> msg , menuAttr : ContextMenuAttribute msg } @@ -54,9 +61,13 @@ type alias Config msg = bankConfig : Config msg -> Bank.Config msg bankConfig config = { toMsg = BankMsg >> ActiveTabMsg >> config.toMsg - , onLogin = BankLogin >> config.toMsg - , onTransfer = BankTransfer >> config.toMsg - , onLogout = BankLogout |> config.toMsg + , batchMsg = config.batchMsg + , bank = config.bank + , onLogin = BankLogin >>> config.toMsg + , onLoginToken = BankLoginToken >>> config.toMsg + , onTransfer = BankTransfer >>>>> config.toMsg + , onChangePassword = BankChangePass >> config.toMsg + , onLogout = BankLogout >> config.toMsg } diff --git a/src/Apps/Browser/Messages.elm b/src/Apps/Browser/Messages.elm index 93185619..0f6d1491 100644 --- a/src/Apps/Browser/Messages.elm +++ b/src/Apps/Browser/Messages.elm @@ -1,8 +1,7 @@ module Apps.Browser.Messages exposing (..) -import Game.Account.Finances.Requests.Login as LoginRequest -import Game.Account.Finances.Requests.Transfer as TransferRequest -import Game.Meta.Types.Network as Network exposing (NIP) +import Game.Account.Finances.Models as Finances +import Game.Meta.Types.Network as Network exposing (NIP, IP) import Game.Servers.Shared exposing (StorageId) import Game.Servers.Filesystem.Shared as Filesystem import Game.Servers.Requests.Browse as BrowseRequest @@ -29,9 +28,11 @@ type Msg | ReqDownload Network.NIP Filesystem.FileEntry StorageId | PublicDownload NIP Filesystem.FileEntry | HandlePasswordAcquired PasswordAcquired.Data - | BankLogin LoginRequest.Payload - | BankTransfer TransferRequest.Payload - | BankLogout + | BankLogin Finances.AccountId String + | BankLoginToken Finances.AccountId String + | BankTransfer String IP Finances.AccountNumber Int + | BankChangePass String + | BankLogout String type TabMsg @@ -44,8 +45,8 @@ type TabMsg | Cracked NIP String | AnyMap NIP | Login NIP String - | HandleBankLogin LoginRequest.Data - | HandleBankTransfer TransferRequest.Data + | HandleBankLogin String + | HandleBankTransfer String | HandleLoginFailed | SelectEndpoint | NewApp DesktopApp diff --git a/src/Apps/Browser/Pages/Bank/Config.elm b/src/Apps/Browser/Pages/Bank/Config.elm index 18e1fd6a..8d209d30 100644 --- a/src/Apps/Browser/Pages/Bank/Config.elm +++ b/src/Apps/Browser/Pages/Bank/Config.elm @@ -1,13 +1,18 @@ module Apps.Browser.Pages.Bank.Config exposing (Config) -import Game.Account.Finances.Requests.Login as LoginRequest -import Game.Account.Finances.Requests.Transfer as TransferRequest +import Game.Account.Finances.Models exposing (AccountId, AccountNumber) +import Game.Bank.Models as Bank +import Game.Meta.Types.Network exposing (IP) import Apps.Browser.Pages.Bank.Messages exposing (..) type alias Config msg = { toMsg : Msg -> msg - , onLogin : LoginRequest.Payload -> msg - , onTransfer : TransferRequest.Payload -> msg - , onLogout : msg + , batchMsg : List msg -> msg + , bank : Bank.Model + , onLogin : AccountId -> String -> msg + , onLoginToken : AccountId -> String -> msg + , onChangePassword : String -> msg + , onTransfer : String -> IP -> AccountNumber -> Int -> msg + , onLogout : String -> msg } diff --git a/src/Apps/Browser/Pages/Bank/Messages.elm b/src/Apps/Browser/Pages/Bank/Messages.elm index c5a8afad..252cd80d 100644 --- a/src/Apps/Browser/Pages/Bank/Messages.elm +++ b/src/Apps/Browser/Pages/Bank/Messages.elm @@ -1,13 +1,13 @@ module Apps.Browser.Pages.Bank.Messages exposing (Msg(..)) -import Game.Account.Finances.Shared exposing (BankAccountData) - type Msg - = HandleLogin BankAccountData + = HandleLogin String | HandleLoginError - | HandleTransfer + | SetTransfer | HandleTransferError + | SetLoading + | Logout | UpdateLoginField String | UpdatePasswordField String | UpdateTransferBankField String diff --git a/src/Apps/Browser/Pages/Bank/Models.elm b/src/Apps/Browser/Pages/Bank/Models.elm index c8c868dc..ee32d7f4 100644 --- a/src/Apps/Browser/Pages/Bank/Models.elm +++ b/src/Apps/Browser/Pages/Bank/Models.elm @@ -1,29 +1,30 @@ -module Apps.Browser.Pages.Bank.Models - exposing - ( Model - , initialModel - , getTitle - , State(..) - ) +module Apps.Browser.Pages.Bank.Models exposing (..) import Game.Meta.Types.Network.Site as Site -import Game.Meta.Types.Network exposing (NIP) -import Game.Account.Finances.Models exposing (AccountNumber) -import Game.Account.Finances.Shared exposing (BankAccountData) +import Game.Meta.Types.Network exposing (IP) +import Game.Account.Finances.Models exposing (AccountNumber, AtmId) type alias Model = { title : String - , nip : NIP - , loggedIn : Bool - , bankState : State - , error : Maybe String - , accountData : Maybe BankAccountData - , toBankTransfer : Maybe NIP - , toAccountTransfer : Maybe AccountNumber - , accountNum : Maybe AccountNumber - , transferValue : Maybe Int + , atmId : AtmId + , sessionId : Maybe String + , state : State + } + + +type alias LoginInformation = + { login : Maybe Int , password : Maybe String + , error : Maybe String + } + + +type alias TransferInformation = + { destinyAccount : Maybe AccountNumber + , destinyBank : Maybe IP + , value : Maybe Int + , error : Maybe String } @@ -32,27 +33,212 @@ type alias Model = type State - = Login + = Login LoginInformation | Main - | Transfer + | Loading + | Transfer TransferInformation + | TransferSuccess initialModel : Site.Url -> Site.BankContent -> Model initialModel url content = { title = content.title - , nip = content.nip - , loggedIn = False - , bankState = Login - , error = Nothing - , accountData = Nothing - , toBankTransfer = Nothing - , toAccountTransfer = Nothing - , accountNum = Nothing - , transferValue = Nothing - , password = Nothing + , atmId = content.atmId + , sessionId = Nothing + , state = Login (LoginInformation Nothing Nothing Nothing) } + +-- Getters and Setters + + getTitle : Model -> String getTitle { title } = title ++ " Bank" + + +getUsername : Model -> Maybe Int +getUsername model = + case model.state of + Login info -> + info.login + + _ -> + Nothing + + +getPassword : Model -> Maybe String +getPassword model = + case model.state of + Login info -> + info.password + + _ -> + Nothing + + +getLoginError : Model -> Maybe String +getLoginError model = + case model.state of + Login info -> + info.error + + _ -> + Nothing + + +getTransferDestinyBankIp : Model -> Maybe IP +getTransferDestinyBankIp model = + case model.state of + Transfer info -> + info.destinyBank + + _ -> + Nothing + + +getTransferDestinyAcc : Model -> Maybe Int +getTransferDestinyAcc model = + case model.state of + Transfer info -> + info.destinyAccount + + _ -> + Nothing + + +getTransferValue : Model -> Maybe Int +getTransferValue model = + case model.state of + Transfer info -> + info.value + + _ -> + Nothing + + +getTransferError : Model -> Maybe String +getTransferError model = + case model.state of + Transfer info -> + info.error + + _ -> + Nothing + + +setUsername : String -> Model -> Model +setUsername string model = + case model.state of + Login info -> + if String.isEmpty string then + { model | state = Login { info | login = Nothing } } + else + let + newUsername = + Just <| Result.withDefault 0 <| String.toInt string + in + if String.length string > 6 then + model + else + { model | state = Login { info | login = newUsername } } + + _ -> + model + + +setPassword : String -> Model -> Model +setPassword string model = + case model.state of + Login info -> + if String.isEmpty string then + { model | state = Login { info | password = Nothing } } + else + { model | state = Login { info | password = Just string } } + + _ -> + model + + +setLoginError : String -> Model -> Model +setLoginError string model = + case model.state of + Login info -> + if String.isEmpty string then + { model | state = Login { info | error = Nothing } } + else + { model | state = Login { info | error = Just string } } + + _ -> + model + + +setTransferDestinyBankIp : IP -> Model -> Model +setTransferDestinyBankIp ip model = + case model.state of + Transfer info -> + if String.isEmpty ip then + { model | state = Transfer { info | destinyBank = Nothing } } + else + { model | state = Transfer { info | destinyBank = Just ip } } + + _ -> + model + + +setTransferDestinyAcc : String -> Model -> Model +setTransferDestinyAcc string model = + case model.state of + Transfer info -> + if String.isEmpty string then + { model | state = Transfer { info | destinyAccount = Nothing } } + else + let + acc = + Just <| Result.withDefault 0 <| String.toInt string + in + { model | state = Transfer { info | destinyAccount = acc } } + + _ -> + model + + +setTransferValue : String -> Model -> Model +setTransferValue string model = + case model.state of + Transfer info -> + if String.isEmpty string then + { model | state = Transfer { info | value = Nothing } } + else + let + value = + Just <| Result.withDefault 0 <| String.toInt string + in + { model | state = Transfer { info | value = value } } + + _ -> + model + + +setTransferError : String -> Model -> Model +setTransferError string model = + case model.state of + Transfer info -> + if String.isEmpty string then + { model | state = Transfer { info | error = Nothing } } + else + { model | state = Transfer { info | error = Just string } } + + _ -> + model + + +isLogged : Model -> Bool +isLogged model = + case model.sessionId of + Just _ -> + True + + Nothing -> + False diff --git a/src/Apps/Browser/Pages/Bank/Resources.elm b/src/Apps/Browser/Pages/Bank/Resources.elm new file mode 100644 index 00000000..57be48b8 --- /dev/null +++ b/src/Apps/Browser/Pages/Bank/Resources.elm @@ -0,0 +1,16 @@ +module Apps.Browser.Pages.Bank.Resources exposing (..) + +prefix: String +prefix = + "bnk" + +type Classes + = MainContainer + | Header + | Footer + | MiddleContainer + | LoginForm + | Input + | BalanceContainer + | ActionsContainer + | TransferForm \ No newline at end of file diff --git a/src/Apps/Browser/Pages/Bank/Style.elm b/src/Apps/Browser/Pages/Bank/Style.elm new file mode 100644 index 00000000..e34b9c70 --- /dev/null +++ b/src/Apps/Browser/Pages/Bank/Style.elm @@ -0,0 +1,93 @@ +module Apps.Browser.Pages.Bank.Style exposing (..) + +import Css exposing (..) +import Css.Namespace exposing (namespace) +import UI.Common + exposing + ( flexContainerHorz + , flexContainerVert + , internalPadding + ) +import Css.Elements exposing (input, button) +import Apps.Browser.Pages.Bank.Resources exposing (Classes(..), prefix) + +css : Stylesheet +css = + (stylesheet << namespace prefix) + [ class MainContainer + [ width (pct 98) + , height (pct 100) + , overflowX hidden + , overflowY auto + , internalPadding + , children + [ class Header + [ flexContainerHorz + , height (pct 10) + , width (pct 100) + ] + , class MiddleContainer + [ flexContainerVert + , height (pct 80) + , width (pct 100) + , justifyContent spaceBetween + , children + [ class LoginForm + [ flexContainerVert + , height (px 150) + , width (px 310) + , justifyContent center + , alignItems center + , margin2 (px 0) auto + , children + [ each [ input ] + [ width (px 150) + , height (px 16) + , marginBottom (px 8) + ] + , each [ button ] + [ height (px 16) + ] + ] + ] + , class TransferForm + [ flexContainerVert + , height (px 150) + , width (px 310) + , justifyContent center + , alignItems center + , margin2 (px 0) auto + , children + [ each [ input ] + [ width (px 150) + , height (px 24) + , marginBottom (px 8) + ] + ] + ] + , class BalanceContainer + [ flexContainerHorz + , width (pct 100) + , alignItems flexEnd + , height (px 16) + ] + , class ActionsContainer + [ flexContainerHorz + , width (pct 100) + , height (px 24) + , children + [ each [ button ] + [ marginRight (px 8) + ] + ] + ] + ] + ] + , class Footer + [ flexContainerHorz + , height (pct 10) + , width (pct 100) + ] + ] + ] + ] \ No newline at end of file diff --git a/src/Apps/Browser/Pages/Bank/Update.elm b/src/Apps/Browser/Pages/Bank/Update.elm index c4cdfe9c..bafa96e8 100644 --- a/src/Apps/Browser/Pages/Bank/Update.elm +++ b/src/Apps/Browser/Pages/Bank/Update.elm @@ -1,11 +1,11 @@ module Apps.Browser.Pages.Bank.Update exposing (update) import Utils.React as React exposing (React) -import Game.Meta.Types.Network as Network exposing (NIP) +import Utils.Maybe as Maybe +import Game.Bank.Models as Bank import Apps.Browser.Pages.Bank.Config exposing (..) import Apps.Browser.Pages.Bank.Models exposing (..) import Apps.Browser.Pages.Bank.Messages exposing (..) -import Game.Account.Finances.Shared exposing (BankAccountData) type alias UpdateResponse msg = @@ -19,18 +19,24 @@ update : -> UpdateResponse msg update config msg model = case msg of - HandleLogin accData -> - handleLogin config accData model + HandleLogin sessionId -> + handleLogin config sessionId model HandleLoginError -> handleLoginError config model - HandleTransfer -> - handleTransfer config model + SetTransfer -> + setTransfer config model HandleTransferError -> handleTransferError config model + Logout -> + onLogout config model + + SetLoading -> + onSetLoading model + UpdateLoginField str -> onUpdateLoginField config str model @@ -53,15 +59,7 @@ onUpdateLoginField : -> Model -> UpdateResponse msg onUpdateLoginField config str model = - if (String.contains "-" str) then - ( model, React.none ) - else - case (String.toInt str) of - Result.Ok num -> - ( { model | accountNum = Just num }, React.none ) - - Result.Err _ -> - ( model, React.none ) + React.update <| setUsername str model onUpdatePasswordField : @@ -70,7 +68,7 @@ onUpdatePasswordField : -> Model -> UpdateResponse msg onUpdatePasswordField config str model = - ( { model | password = Just str }, React.none ) + React.update <| setPassword str model onUpdateTransferBankField : @@ -79,10 +77,7 @@ onUpdateTransferBankField : -> Model -> UpdateResponse msg onUpdateTransferBankField config str model = - if (String.contains "-" str) then - ( model, React.none ) - else - ( { model | toBankTransfer = Just (Network.fromString str) }, React.none ) + React.update <| setTransferDestinyBankIp str model onUpdateTransferAccountField : @@ -91,15 +86,7 @@ onUpdateTransferAccountField : -> Model -> UpdateResponse msg onUpdateTransferAccountField config str model = - if (String.contains "-" str) then - ( model, React.none ) - else - case (String.toInt str) of - Result.Ok num -> - ( { model | toAccountTransfer = Just num }, React.none ) - - Result.Err _ -> - ( model, React.none ) + React.update <| setTransferDestinyAcc str model onUpdateTransferValueField : @@ -108,30 +95,25 @@ onUpdateTransferValueField : -> Model -> UpdateResponse msg onUpdateTransferValueField config str model = - if (String.contains "-" str) then - ( model, React.none ) - else - case (String.toInt str) of - Result.Ok num -> - ( { model | transferValue = Just num }, React.none ) + React.update <| setTransferValue str model + - Result.Err _ -> - ( model, React.none ) +onSetLoading : Model -> UpdateResponse msg +onSetLoading model = + ( { model | state = Loading }, React.none ) handleLogin : Config msg - -> BankAccountData + -> String -> Model -> UpdateResponse msg -handleLogin config accData model = +handleLogin config sessionId model = let model_ = { model - | loggedIn = True - , bankState = Main - , accountData = Just accData - , error = Nothing + | state = Main + , sessionId = Just sessionId } in ( model_, React.none ) @@ -142,23 +124,50 @@ handleLoginError : -> Model -> UpdateResponse msg handleLoginError config model = + React.update <| setLoginError "Invalid Login Information" model + + +onLogout : Config msg -> Model -> UpdateResponse msg +onLogout config model = let model_ = - { model | error = Just "Invalid Login Information" } + { model + | sessionId = Nothing + , state = Login (LoginInformation Nothing Nothing Nothing) + } + + mapper = + flip Bank.getAccountId config.bank + + accountId = + Maybe.map mapper model.sessionId + + + react = + case Maybe.uncurry accountId model.sessionId of + Just (accountId, sessionId) -> + React.msg <| config.onLogout sessionId + + Nothing -> + React.none in - ( model_, React.none ) + ( model_, react ) -handleTransfer : +setTransfer : Config msg -> Model -> UpdateResponse msg -handleTransfer config model = +setTransfer config model = let model_ = - { model | bankState = Transfer } + { model + | state = + TransferInformation Nothing Nothing Nothing Nothing + |> Transfer + } in - ( model_, React.none ) + React.update model_ handleTransferError : @@ -166,8 +175,4 @@ handleTransferError : -> Model -> UpdateResponse msg handleTransferError config model = - let - model_ = - { model | error = Just "Transfer Error" } - in - ( model_, React.none ) + React.update <| setTransferError "Transfer Error" model diff --git a/src/Apps/Browser/Pages/Bank/View.elm b/src/Apps/Browser/Pages/Bank/View.elm index 9a767882..2d7f75e2 100644 --- a/src/Apps/Browser/Pages/Bank/View.elm +++ b/src/Apps/Browser/Pages/Bank/View.elm @@ -4,12 +4,12 @@ import Html exposing (..) import Html.Attributes exposing (..) import Html.CssHelpers import Html.Events exposing (..) -import Apps.Browser.Resources exposing (Classes(..), prefix) +import Game.Bank.Models as Bank +import Apps.Browser.Pages.Bank.Resources exposing (Classes(..), prefix) import Apps.Browser.Pages.Bank.Config exposing (..) import Apps.Browser.Pages.Bank.Models exposing (..) import Apps.Browser.Pages.Bank.Messages exposing (..) -import Game.Account.Finances.Shared exposing (toMoney) -import Game.Meta.Types.Network as Network +import Game.Bank.Shared exposing (toMoney) { id, class, classList } = @@ -18,29 +18,45 @@ import Game.Meta.Types.Network as Network view : Config msg -> Model -> Html msg view config model = - case model.bankState of - Login -> + case model.state of + Login _ -> viewLogin config model Main -> viewMain config model - Transfer -> + Loading -> + viewLoading config model + + Transfer _ -> viewTransfer config model + TransferSuccess -> + viewTransferSuccess config model + viewLogin : Config msg -> Model -> Html msg viewLogin config model = - div [] + div [ class [ MainContainer ] ] [ viewHeader model , viewLoginForm config model , viewFooter model ] +viewLoading : Config msg -> Model -> Html msg +viewLoading config model = + div [ class [ MainContainer ] ] [ text "Loading..." ] + + +viewTransferSuccess : Config msg -> Model -> Html msg +viewTransferSuccess config model = + div [ class [ MainContainer ] ] [ text "Transfer started." ] + + viewMain : Config msg -> Model -> Html msg viewMain config model = - div [] + div [ class [ MainContainer ] ] [ viewHeader model , viewMainCointainer config model , viewFooter model @@ -49,7 +65,7 @@ viewMain config model = viewTransfer : Config msg -> Model -> Html msg viewTransfer config model = - div [] + div [ class [ MainContainer ] ] [ viewHeader model , viewTransferForm config model , viewFooter model @@ -58,12 +74,12 @@ viewTransfer config model = viewHeader : Model -> Html msg viewHeader model = - div [] [ text model.title ] + div [ class [ Header ] ] [ text model.title ] viewFooter : Model -> Html msg viewFooter model = - div [] [ text model.title ] + div [ class [ Footer ] ] [ text model.title ] viewLoginForm : Config msg -> Model -> Html msg @@ -73,12 +89,14 @@ viewLoginForm ({ toMsg, onLogin } as config) model = [ placeholder "Password" , type_ "password" , onInput (UpdatePasswordField >> toMsg) + , class [ Input ] ] |> (++) (renderPasswordValue model) loginAttr = [ placeholder "Account Number" , onInput (UpdateLoginField >> toMsg) + , class [ Input ] ] |> (++) (renderLoginValue model) @@ -88,35 +106,41 @@ viewLoginForm ({ toMsg, onLogin } as config) model = password = input passwordAttr [] in - Html.form [ action "javascript:void(0);" ] - [ login - , br [] [] - , password - , div [] [ error model ] - , br [] [] - , input - (submitLoginAttr config model) - [] + div [ class [ MiddleContainer ] ] + [ Html.form [ class [ LoginForm ], action "javascript:void(0);" ] + [ login + , br [] [] + , password + , div [] [ error model ] + , br [] [] + , input + (submitLoginAttr config model) + [] + ] ] -viewMainCointainer : Config msg -> Model -> Html msg -viewMainCointainer { toMsg } model = - let - renderBalance model = - case model.accountData of - Just data -> - text <| toMoney data.balance +renderBalance : Config msg -> Model -> Html msg +renderBalance config model = + model + |> (.sessionId) + |> Maybe.andThen ((flip Bank.getSession) config.bank) + |> Maybe.map (.accountCache) + |> Maybe.map (.balance) + |> Maybe.map (\a -> "Available USD: " ++ (toMoney a)) + |> Maybe.withDefault "Balance is not Availiable" + |> text - Nothing -> - text "" - in - div [] - [ div [] - [ renderBalance model ] - , div [] - [] +viewMainCointainer : Config msg -> Model -> Html msg +viewMainCointainer ({ toMsg } as config) model = + div [ class [ MiddleContainer ] ] + [ div [ class [ BalanceContainer ] ] + [ renderBalance config model ] + , div [ class [ ActionsContainer ] ] + [ button (buttonCPAttr config model) [ text "Change Password" ] + , button (buttonTransferAttr config model) [ text "Transfer" ] ] + ] viewTransferForm : Config msg -> Model -> Html msg @@ -127,125 +151,182 @@ viewTransferForm ({ toMsg, onTransfer } as config) model = , onInput (toMsg << UpdateTransferBankField) ] |> (++) (renderToTransferBank model) + + accountAttr info = + [ placeholder "Account Number" + , info.destinyAccount + |> Maybe.map toString + |> Maybe.withDefault "" + |> value + , onInput (toMsg << UpdateTransferAccountField) + ] + + valueAttr info = + [ placeholder "Value" + , info.value + |> Maybe.map toString + |> Maybe.withDefault "" + |> value + , onInput (toMsg << UpdateTransferValueField) + ] in - Html.form [ action "javascript:void(0);" ] - [ input - bankIPAttr - [] - , br [] [] - , input - [ placeholder "Account Number" - , type_ "number" - , value (toString model.toAccountTransfer) - , onInput (toMsg << UpdateTransferAccountField) - ] - [] - , br [] [] - , input - [ placeholder "Value" - , type_ "number" - , value (toString model.transferValue) - , onInput (toMsg << UpdateTransferValueField) - ] - [] - , div [] [ error model ] - , input - (submitTransferAttr config model) - [] + case model.state of + Transfer info -> + div [ class [ MiddleContainer ] ] + [ Html.form + [ class [ TransferForm ] + , action "javascript:void(0);" + ] + [ input bankIPAttr [] + , br [] [] + , input (accountAttr info) [] + , br [] [] + , input (valueAttr info) [] + , div [] [ error model ] + , br [] [] + , input (submitTransferAttr config model) [] + ] + ] + + _ -> + text "" + + +buttonCPAttr : Config msg -> Model -> List (Attribute msg) +buttonCPAttr config model = + case model.sessionId of + Just sessionId -> + [ name "Change Password" + , onClick <| config.onChangePassword sessionId + ] + + Nothing -> + [ disabled True ] + +buttonTransferAttr : Config msg -> Model -> List (Attribute msg) +buttonTransferAttr {toMsg} model = + case model.sessionId of + Just sessionId -> + [ name "Transfer" + , SetTransfer + |> toMsg + |> onClick ] + Nothing -> + [ disabled True ] + + +submitButtonBaseAttr : List (Attribute msg) +submitButtonBaseAttr = + [ type_ "submit" + , value "Submit" + ] + submitLoginAttr : Config msg -> Model -> List (Attribute msg) -submitLoginAttr { onLogin } model = +submitLoginAttr { onLogin, toMsg, batchMsg } model = let - baseAttr = - [ type_ "submit" - , value "Submit" + applier login password = + [ onLogin ( model.atmId, login ) password + , toMsg SetLoading ] + |> batchMsg + |> onClick + |> flip (::) submitButtonBaseAttr + + ( login, password ) = + case model.state of + Login info -> + (,) info.login info.password + + _ -> + (,) Nothing Nothing in - case ( model.accountNum, model.password ) of - ( Just login, Just password ) -> - let - request = - { bank = model.nip - , accountNum = login - , password = password - } - in - (onClick <| onLogin request) :: baseAttr + case Maybe.map2 applier login password of + Just attr -> + attr - _ -> - (disabled True) :: baseAttr + Nothing -> + (disabled True) :: submitButtonBaseAttr submitTransferAttr : Config msg -> Model -> List (Attribute msg) submitTransferAttr { onTransfer } model = let - baseAttr = - [ type_ "submit" - , value "Submit" - ] + applier sessionId accNum bankIp value = + onTransfer sessionId bankIp accNum value + |> onClick + |> flip (::) submitButtonBaseAttr + + ( sessionId, accNum, bankIp, value ) = + case model.state of + Transfer info -> + ( model.sessionId + , info.destinyAccount + , info.destinyBank + , info.value + ) + + _ -> + ( model.sessionId, Nothing, Nothing, Nothing ) in - case - ( model.accountNum - , model.toBankTransfer - , model.toAccountTransfer - , model.password - , model.transferValue - ) - of - ( Just fromAccount, Just toBank, Just toAccount, Just password, Just value ) -> - let - request = - { toBank = model.nip - , toAcc = fromAccount - , fromBank = toBank - , fromAcc = toAccount - , password = password - , value = value - } - in - (onClick <| onTransfer request) :: baseAttr + case Maybe.map4 applier sessionId accNum bankIp value of + Just attr -> + attr - _ -> - (disabled True) :: baseAttr + Nothing -> + (disabled True) :: submitButtonBaseAttr error : Model -> Html msg error model = - case model.error of - Just error -> - text error + case model.state of + Login info -> + text (Maybe.withDefault "" info.error) - Nothing -> + Transfer info -> + text (Maybe.withDefault "" info.error) + + _ -> text "" renderToTransferBank : Model -> List (Attribute msg) renderToTransferBank model = - case model.toBankTransfer of - Just toBankTransfer -> - [ value (Network.toString toBankTransfer) ] + case model.state of + Transfer info -> + case info.destinyBank of + Just destinyBank -> + [ value destinyBank ] - Nothing -> + Nothing -> + [] + + _ -> [] renderPasswordValue : Model -> List (Attribute msg) renderPasswordValue model = - case model.password of - Just password -> - [ value password ] + case model.state of + Login info -> + case info.password of + Just password -> + [ value password ] - Nothing -> + Nothing -> + [] + + _ -> [] renderLoginValue : Model -> List (Attribute msg) renderLoginValue model = - case model.accountNum of - Just login -> - [ value <| toString login ] + case model.state of + Login info -> + [ value <| Maybe.withDefault "" (Maybe.map toString info.login) ] - Nothing -> + _ -> [] diff --git a/src/Apps/Browser/Pages/Configs.elm b/src/Apps/Browser/Pages/Configs.elm deleted file mode 100644 index 996acf1f..00000000 --- a/src/Apps/Browser/Pages/Configs.elm +++ /dev/null @@ -1,57 +0,0 @@ -module Apps.Browser.Pages.Configs exposing (..) - -import Game.Account.Finances.Models exposing (BankLoginRequest, BankTransferRequest) -import Apps.Browser.Config as Browser -import Apps.Browser.Pages.Bank.Config as Bank -import Apps.Browser.Pages.DownloadCenter.Config as DownloadCenter -import Apps.Browser.Pages.Home.Config as Home -import Apps.Browser.Pages.Webserver.Config as Webserver -import Apps.Browser.Messages exposing (..) - - -bankConfig : Bank.Config Msg -bankConfig = - { toMsg = BankMsg >> ActiveTabMsg - , onLogin = \a -> BankLogin a - , onTransfer = \a -> BankTransfer a - , onLogout = BankLogout - } - - -downloadCenterConfig : Browser.Config msg -> DownloadCenter.Config Msg -downloadCenterConfig config = - { toMsg = DownloadCenterMsg >> ActiveTabMsg - , batchMsg = config.batchMsg - , onLogin = \a b -> ActiveTabMsg <| Login a b - , onLogout = ActiveTabMsg Logout - , onCrack = Crack >> ActiveTabMsg - , onAnyMap = AnyMap >> ActiveTabMsg - , onPublicDownload = PublicDownload - , onSetEndpoint = config.onSetEndpoint - , onSelectEndpoint = ActiveTabMsg SelectEndpoint - , onNewApp = NewApp >> ActiveTabMsg - , endpoints = config.endpoints - } - - -homeConfig : Home.Config Msg -homeConfig = - { onNewTabIn = NewTabIn - , onGoAddress = GoAddress >> ActiveTabMsg - } - - -webserverConfig : Browser.Config msg -> Webserver.Config Msg -webserverConfig config = - { toMsg = WebserverMsg >> ActiveTabMsg - , batchMsg = config.batchMsg - , onLogin = \a b -> ActiveTabMsg <| Login a b - , onLogout = ActiveTabMsg Logout - , onCrack = Crack >> ActiveTabMsg - , onAnyMap = AnyMap >> ActiveTabMsg - , onPublicDownload = PublicDownload - , onSetEndpoint = config.onSetEndpoint - , onSelectEndpoint = ActiveTabMsg SelectEndpoint - , onNewApp = NewApp >> ActiveTabMsg - , endpoints = config.endpoints - } diff --git a/src/Apps/Browser/Pages/Style.elm b/src/Apps/Browser/Pages/Style.elm new file mode 100644 index 00000000..da18e355 --- /dev/null +++ b/src/Apps/Browser/Pages/Style.elm @@ -0,0 +1,9 @@ +module Apps.Browser.Pages.Style exposing (cssList) + +import Css exposing (Stylesheet) +import Apps.Browser.Pages.Bank.Style as Bank + +cssList : List Stylesheet +cssList = + [ Bank.css + ] diff --git a/src/Apps/Browser/Style.elm b/src/Apps/Browser/Style.elm index 5fd81660..d4a0d923 100644 --- a/src/Apps/Browser/Style.elm +++ b/src/Apps/Browser/Style.elm @@ -44,6 +44,7 @@ css = , class Client [ flexContainerVert , height (pct 100) + , width (pct 100) , children [ everything [ flex (int 0) ] diff --git a/src/Apps/Browser/Update.elm b/src/Apps/Browser/Update.elm index 8b10cce3..71f0b8a4 100644 --- a/src/Apps/Browser/Update.elm +++ b/src/Apps/Browser/Update.elm @@ -2,15 +2,16 @@ module Apps.Browser.Update exposing (update) import Dict import Utils.React as React exposing (React) -import Game.Account.Finances.Requests.Login as BankLoginRequest -import Game.Account.Finances.Requests.Transfer as BankTransferRequest +import Game.Account.Finances.Models as Finances +import Game.Bank.Requests.Transfer as BankTransferRequest +import Game.Bank.Shared exposing (..) import Game.Servers.Models as Servers import Game.Servers.Shared exposing (StorageId) import Game.Servers.Filesystem.Shared as Filesystem import Game.Servers.Requests.Browse as BrowseRequest exposing (browseRequest) import Game.Meta.Types.Desktop.Apps exposing (Reference, Requester) import Game.Meta.Types.Context exposing (Context(..)) -import Game.Meta.Types.Network as Network +import Game.Meta.Types.Network as Network exposing (IP) import Apps.Browser.Pages.Webserver.Update as Webserver import Apps.Browser.Pages.Bank.Messages as Bank import Apps.Browser.Pages.Bank.Update as Bank @@ -67,14 +68,20 @@ update config msg model = EveryTabMsg msg -> onEveryTabMsg config msg model - BankLogin request -> - onBankLogin config request model.me model + BankLogin bankAccId password -> + onBankLogin config bankAccId password model - BankTransfer request -> - onBankTransfer config request model.me model + BankLoginToken bankAccId token -> + onBankLoginToken config bankAccId token model - BankLogout -> - onBankLogout config model + BankTransfer sessionId bankIp accNum value -> + onBankTransfer config sessionId bankIp accNum value model + + BankLogout sessionId -> + onBankLogout config sessionId model + + BankChangePass _ -> + React.update model @@ -143,36 +150,64 @@ onReqDownload { onNewPublicDownload } source file storage model = onBankLogin : Config msg - -> BankLoginRequest.Payload - -> Reference + -> Finances.AccountId + -> String -> Model -> UpdateResponse msg -onBankLogin { onBankAccountLogin } request reference model = +onBankLogin { onBankAccountLogin } bankAccId password model = model.nowTab - |> Requester reference - |> onBankAccountLogin request + |> Requester model.me + |> onBankAccountLogin bankAccId password + |> React.msg + |> (,) model + + +onBankLoginToken : + Config msg + -> Finances.AccountId + -> String + -> Model + -> UpdateResponse msg +onBankLoginToken { onBankAccountLoginToken } bankAccId token model = + model.nowTab + |> Requester model.me + |> onBankAccountLoginToken bankAccId token |> React.msg |> (,) model onBankTransfer : Config msg - -> BankTransferRequest.Payload - -> Reference + -> String + -> IP + -> Finances.AccountNumber + -> Int -> Model -> UpdateResponse msg -onBankTransfer { onBankAccountTransfer } request reference model = +onBankTransfer { onBankAccountTransfer } sessionId bankIp accNum value model = model.nowTab - |> Requester reference - |> onBankAccountTransfer request + |> Requester model.me + |> onBankAccountTransfer sessionId bankIp accNum value + |> React.msg + |> (,) model + + +onBankChangePass : Config msg -> String -> Model -> UpdateResponse msg +onBankChangePass { onBankAccountChangePass } sessionId model = + model.nowTab + |> Requester model.me + |> onBankAccountChangePass sessionId |> React.msg |> (,) model -onBankLogout : Config msg -> Model -> UpdateResponse msg -onBankLogout config model = - -- TODO: Bank Logout Request - ( model, React.none ) +onBankLogout : Config msg -> String -> Model -> UpdateResponse msg +onBankLogout { onBankAccountLogout } sessionId model = + model.nowTab + |> Requester model.me + |> onBankAccountLogout sessionId + |> React.msg + |> (,) model @@ -454,23 +489,16 @@ handleBankLogin : Config msg -> Int -> Tab - -> BankLoginRequest.Data + -> String -> Model -> TabUpdateResponse msg -handleBankLogin config tabId tab data model = +handleBankLogin config tabId tab sessionId model = let page = (getTab tabId model.tabs).page ( pageModel, _ ) = - case data of - Ok accountData -> - updatePage config - (BankMsg <| Bank.HandleLogin accountData) - page - - Err _ -> - updatePage config (BankMsg Bank.HandleLoginError) page + updatePage config (BankMsg <| Bank.HandleLogin sessionId) page in ( { tab | page = pageModel }, React.none ) @@ -479,20 +507,15 @@ handleBankTransfer : Config msg -> Int -> Tab - -> BankTransferRequest.Data + -> String -> Model -> TabUpdateResponse msg -handleBankTransfer config tabId tab data model = +handleBankTransfer config tabId tab sessionId model = let page = (getTab tabId model.tabs).page ( pageModel, _ ) = - case data of - Ok () -> - updatePage config (BankMsg Bank.HandleTransfer) page - - Err _ -> - updatePage config (BankMsg Bank.HandleTransferError) page + updatePage config (BankMsg <| Bank.SetTransfer) page in ( { tab | page = pageModel }, React.none ) diff --git a/src/Apps/DBAdmin/View.elm b/src/Apps/DBAdmin/View.elm index 5647276b..9e05b006 100644 --- a/src/Apps/DBAdmin/View.elm +++ b/src/Apps/DBAdmin/View.elm @@ -11,7 +11,7 @@ import Apps.DBAdmin.Messages exposing (Msg(..)) import Apps.DBAdmin.Models exposing (..) import Apps.DBAdmin.Resources exposing (Classes(..), prefix) import Apps.DBAdmin.Tabs.Servers.View as Servers exposing (view) -import Game.Account.Finances.Shared exposing (toMoney) +import Game.Bank.Shared exposing (toMoney) import Game.Account.Database.Models as Database diff --git a/src/Apps/Finance/View.elm b/src/Apps/Finance/View.elm index 48f7b0ac..c8c535f2 100644 --- a/src/Apps/Finance/View.elm +++ b/src/Apps/Finance/View.elm @@ -7,7 +7,7 @@ import UI.Layouts.VerticalList exposing (verticalList) import UI.Layouts.VerticalSticked exposing (verticalSticked) import UI.Elements.HorizontalTabs exposing (hzTabs) import Game.Account.Finances.Models as Finances -import Game.Account.Finances.Shared exposing (toMoney) +import Game.Bank.Shared exposing (toMoney) import Apps.Finance.Config exposing (..) import Apps.Finance.Messages exposing (Msg(..)) import Apps.Finance.Models exposing (..) diff --git a/src/Core/Config.elm b/src/Core/Config.elm index e85b33a5..2df82531 100644 --- a/src/Core/Config.elm +++ b/src/Core/Config.elm @@ -28,6 +28,7 @@ import Game.Account.Bounces.Messages as Bounces import Game.Account.Database.Messages as Database import Game.Account.Finances.Messages as Finances import Game.Account.Notifications.Messages as AccountNotifications +import Game.Bank.Messages as Bank import Game.BackFlix.Messages as BackFlix import Game.Meta.Types.Context exposing (Context) import Game.Meta.Types.Desktop.Apps exposing (Reference, Requester) @@ -77,6 +78,13 @@ websocketConfig flags = onJoinedServer cid value = servers <| Servers.HandleJoinedServer cid value + onJoinedBank = + Bank.HandleJoinedBank >>> bank + + onJoinBankFailed a = + BatchMsg [] + + --bank << Bank.HandleJoinFailed onLeft _ _ = BatchMsg [] in @@ -86,6 +94,8 @@ websocketConfig flags = , onDisconnected = account <| Account.HandleDisconnected , onJoinedAccount = onJoinedAccount , onJoinedServer = onJoinedServer + , onJoinedBank = onJoinedBank + , onJoinBankFailed = onJoinBankFailed , onJoinFailedServer = Web.HandleJoinServerFailed >> web , onLeft = onLeft , onEvent = HandleEvent @@ -141,7 +151,8 @@ eventsConfig = onBounceCreated rId ( id, bounce ) = bounces <| Bounces.HandleCreated rId id bounce in - { onServerPasswordAcquired = onServerPasswordAcquired + { batchMsg = BatchMsg + , onServerPasswordAcquired = onServerPasswordAcquired , onStoryStepProceeded = onStoryStepProceeded , onStoryEmailSent = onStoryEmailSent , onStoryEmailReplyUnlocked = onStoryEmailReplyUnlocked @@ -160,6 +171,30 @@ eventsConfig = forBackFlix = { onNewLog = BackFlix.HandleCreate >> backflix } + forBank = + let + onBankLogin (accId, balance, pass) = + bank <| Bank.HandleLoggedIn accId balance pass + + onBankLogout = + BatchMsg [] + + onBankAccountUpdated = + BatchMsg [] + + onBankAccountRemoved = + BatchMsg [] + + onBankAccountPasswordRevealed = + BatchMsg [] + in + { onBankLogin = onBankLogin + , onBankLogout = onBankLogout + , onBankAccountUpdated = onBankAccountUpdated + , onBankAccountRemoved = onBankAccountRemoved + , onBankAccountPasswordRevealed = onBankAccountPasswordRevealed + } + forServer = let onFileAdded cid ( id, data ) = @@ -194,6 +229,7 @@ eventsConfig = in { forAccount = forAccount , forBackFlix = forBackFlix + , forBank = forBank , forServer = forServer } @@ -205,6 +241,13 @@ gameConfig = \cid payload -> ws <| Ws.HandleJoin (ServerChannel cid) payload + onJoinBank id requestId payload = + ws <| Ws.HandleJoin (BankChannel id requestId) (Just payload) + + onLeaveBank = + \bankAccountId requestId -> + ws <| Ws.HandleLeave (BankChannel bankAccountId requestId) + onConnected = \accountId -> BatchMsg @@ -220,16 +263,18 @@ gameConfig = in { toMsg = GameMsg , batchMsg = BatchMsg + , awaitEvent = HandleAwait , onJoinServer = onJoinServer + , onJoinBank = onJoinBank + , onLeaveBank = onLeaveBank , onError = HandleCrash + , onSendBankSessionId = Browser.HandleBankLogin >> browserTab , onJoinFailed = browserTab Browser.HandleLoginFailed , onNewGateway = Setup.HandleJoinedServer >> setup , onConnected = onConnected , onDisconnected = HandleShutdown , onAccountToast = Toast.HandleAccount >> toast , onServerToast = Toast.HandleServers >>> toast - , onBankAccountLogin = Browser.HandleBankLogin >> browserTab - , onBankAccountTransfer = Browser.HandleBankTransfer >> browserTab , onReloadBounce = onReloadBounce , onReloadIfBounceLoaded = onReloadIfBounceLoaded } @@ -312,6 +357,11 @@ ws = WebsocketMsg +bank : Bank.Msg -> Msg +bank = + Game.BankMsg >> game + + setup : Setup.Msg -> Msg setup = SetupMsg diff --git a/src/Core/Stylesheets.elm b/src/Core/Stylesheets.elm index af730c81..9fb6c130 100644 --- a/src/Core/Stylesheets.elm +++ b/src/Core/Stylesheets.elm @@ -13,6 +13,7 @@ import OS.WindowManager.Style as WindowManager import OS.WindowManager.Dock.Style as Dock import OS.WindowManager.Sidebar.Style as Sidebar import Apps.Style as Apps +import Apps.Browser.Pages.Style as BrowserPages port files : CssFileStructure -> Cmd msg @@ -36,6 +37,7 @@ fileStructure = , Sidebar.css ] ++ Apps.cssList + ++ BrowserPages.cssList ) ) ] diff --git a/src/Core/Update.elm b/src/Core/Update.elm index 0cdc0341..75558125 100644 --- a/src/Core/Update.elm +++ b/src/Core/Update.elm @@ -93,7 +93,7 @@ update msg model = awaitMsgs = case maybeMsg of Just msg -> - [ msg ] + Debug.log "" [ msg ] Nothing -> [] diff --git a/src/Decoders/Bank.elm b/src/Decoders/Bank.elm index 994b95d6..f0d2f33d 100644 --- a/src/Decoders/Bank.elm +++ b/src/Decoders/Bank.elm @@ -1,4 +1,4 @@ -module Decoders.Bank exposing (accountData) +module Decoders.Bank exposing (accountData, bankLogin) import Json.Decode as Decode exposing @@ -9,11 +9,24 @@ import Json.Decode as Decode , string , field ) -import Json.Decode.Pipeline exposing (decode, required) -import Game.Account.Finances.Shared exposing (BankAccountData) +import Json.Decode.Pipeline exposing (decode, required, custom) +import Game.Bank.Shared exposing (BankAccountData) accountData : Decoder BankAccountData accountData = decode BankAccountData |> required "balance" int + +accountId : Decoder (String, Int) +accountId = + decode (,) + |> required "atm_id" string + |> required "account_number" int + +bankLogin : Decoder ((String, Int), Int, String) +bankLogin = + decode (,,) + |> custom accountId + |> required "balance" int + |> required "password" string \ No newline at end of file diff --git a/src/Decoders/Database.elm b/src/Decoders/Database.elm index 5d5c81cd..99d579b7 100644 --- a/src/Decoders/Database.elm +++ b/src/Decoders/Database.elm @@ -118,7 +118,7 @@ hackedBankAccountId : Decoder HackedBankAccountID hackedBankAccountId = decode (,) |> required "atm_id" string - |> required "account_num" int + |> required "account_number" int hackedBankAccount : Decoder HackedBankAccount diff --git a/src/Decoders/Game.elm b/src/Decoders/Game.elm index 5fa2fcba..20a8a917 100644 --- a/src/Decoders/Game.elm +++ b/src/Decoders/Game.elm @@ -70,6 +70,7 @@ bootstrap : Model -> Decoder ( Model, ServersToJoin ) bootstrap game = decode Model |> account game + |> hardcoded game.bank |> inventory game |> hardcoded game.servers |> hardcoded game.meta diff --git a/src/Driver/Websocket/Channels.elm b/src/Driver/Websocket/Channels.elm index ccefb818..a46b1cf9 100644 --- a/src/Driver/Websocket/Channels.elm +++ b/src/Driver/Websocket/Channels.elm @@ -1,12 +1,14 @@ module Driver.Websocket.Channels exposing (..) import Game.Account.Models as Account +import Game.Account.Finances.Models exposing (AccountId) import Game.Servers.Shared as Servers type Channel = AccountChannel Account.ID | ServerChannel Servers.CId + | BankChannel AccountId String | BackFlixChannel @@ -24,5 +26,8 @@ getAddress channel = Servers.EndpointCId ( id, ip ) -> "server:" ++ id ++ "@" ++ ip + BankChannel ( atmId, accNum ) _ -> + "bank:" ++ (toString accNum) ++ "@" ++ atmId + BackFlixChannel -> "logflix" diff --git a/src/Driver/Websocket/Config.elm b/src/Driver/Websocket/Config.elm index 471d3c65..23ab68b5 100644 --- a/src/Driver/Websocket/Config.elm +++ b/src/Driver/Websocket/Config.elm @@ -2,6 +2,7 @@ module Driver.Websocket.Config exposing (..) import Json.Decode exposing (Value) import Core.Flags as Core +import Game.Bank.Shared exposing (..) import Game.Servers.Shared exposing (CId) import Driver.Websocket.Channels exposing (..) import Driver.Websocket.Messages exposing (..) @@ -14,6 +15,8 @@ type alias Config msg = , onDisconnected : msg , onJoinedAccount : Value -> msg , onJoinedServer : CId -> Value -> msg + , onJoinedBank : String -> Value -> msg + , onJoinBankFailed : String -> msg , onJoinFailedServer : CId -> msg , onLeft : Channel -> Maybe Value -> msg , onEvent : Channel -> Result String ( String, String, Value ) -> msg diff --git a/src/Driver/Websocket/Messages.elm b/src/Driver/Websocket/Messages.elm index beb444e6..950d7cdd 100644 --- a/src/Driver/Websocket/Messages.elm +++ b/src/Driver/Websocket/Messages.elm @@ -1,6 +1,7 @@ module Driver.Websocket.Messages exposing (..) import Driver.Websocket.Channels exposing (..) +import Game.Account.Finances.Models exposing (AccountId) import Json.Decode exposing (Value) diff --git a/src/Driver/Websocket/Update.elm b/src/Driver/Websocket/Update.elm index 8c6da366..a66ad62d 100644 --- a/src/Driver/Websocket/Update.elm +++ b/src/Driver/Websocket/Update.elm @@ -5,6 +5,8 @@ import Json.Decode exposing (Value, decodeValue, value, string, field, maybe, ma import Json.Decode.Pipeline exposing (decode, required, optional) import Phoenix.Channel as Channel import Utils.React as React exposing (React) +import Decoders.Bank as Bank +import Game.Account.Finances.Models exposing (AccountId) import Driver.Websocket.Config exposing (..) import Driver.Websocket.Channels exposing (..) import Driver.Websocket.Messages exposing (..) @@ -60,6 +62,9 @@ onJoined config channel payload model = ServerChannel cid -> React.msg <| config.onJoinedServer cid payload_ + BankChannel _ requestId -> + React.msg <| config.onJoinedBank requestId payload_ + BackFlixChannel -> React.none in @@ -76,6 +81,9 @@ onJoinFailed config channel payload model = ServerChannel cid -> React.msg <| config.onJoinFailedServer cid + BankChannel _ requestId -> + React.msg <| config.onJoinBankFailed requestId + _ -> React.none in @@ -130,7 +138,6 @@ handleJoin config channel payload model = in ( { model | channels = channels }, React.none ) - handleLeave : Config msg -> Channel diff --git a/src/Events/Account/Config.elm b/src/Events/Account/Config.elm index 33261b14..d077a173 100644 --- a/src/Events/Account/Config.elm +++ b/src/Events/Account/Config.elm @@ -17,7 +17,8 @@ import Events.Account.Handlers.VirusCollected as VirusCollected type alias Config msg = - { onServerPasswordAcquired : ServerPasswordAcquired.Data -> msg + { batchMsg : List msg -> msg + , onServerPasswordAcquired : ServerPasswordAcquired.Data -> msg , onStoryStepProceeded : StoryStepProceeded.Data -> msg , onStoryEmailSent : StoryEmailSent.Data -> msg , onStoryEmailReplyUnlocked : StoryEmailReplyUnlocked.Data -> msg diff --git a/src/Events/Account/Handler.elm b/src/Events/Account/Handler.elm index 511be7b7..5f62ff7b 100644 --- a/src/Events/Account/Handler.elm +++ b/src/Events/Account/Handler.elm @@ -8,8 +8,6 @@ import Events.Account.Handlers.StoryEmailReplyUnlocked as StoryEmailReplyUnlocke import Events.Account.Handlers.StoryEmailReplySent as StoryEmailReplySent import Events.Account.Handlers.BankAccountUpdated as BankAccountUpdated import Events.Account.Handlers.BankAccountClosed as BankAccountClosed -import Events.Account.Handlers.DbAccountUpdated as DbAccountUpdated -import Events.Account.Handlers.DbAccountRemoved as DbAccountRemoved import Events.Account.Handlers.TutorialFinished as TutorialFinished import Events.Account.Handlers.BounceCreated as BounceCreated import Events.Account.Handlers.BounceUpdated as BounceUpdated @@ -42,11 +40,8 @@ events config requestId name value = "bank_account_closed" -> BankAccountClosed.handler config.onBankAccountClosed value - "db_account_updated" -> - DbAccountUpdated.handler config.onDbAccountUpdated value - - "db_account_removed" -> - DbAccountRemoved.handler config.onDbAccountRemoved value + "bank_account_password_changed" -> + Err "" "tutorial_finished" -> TutorialFinished.handler config.onTutorialFinished value diff --git a/src/Events/Bank/Config.elm b/src/Events/Bank/Config.elm new file mode 100644 index 00000000..5cf53348 --- /dev/null +++ b/src/Events/Bank/Config.elm @@ -0,0 +1,11 @@ +module Events.Bank.Config exposing (..) + +import Events.Bank.Handlers.Login as BankLogin + +type alias Config msg = + { onBankLogin : BankLogin.Data -> msg + , onBankLogout : msg + , onBankAccountUpdated : msg + , onBankAccountRemoved : msg + , onBankAccountPasswordRevealed : msg + } diff --git a/src/Events/Bank/Handler.elm b/src/Events/Bank/Handler.elm new file mode 100644 index 00000000..db1a7fd6 --- /dev/null +++ b/src/Events/Bank/Handler.elm @@ -0,0 +1,31 @@ +module Events.Bank.Handler exposing (events) + +import Events.Shared exposing (Router) +import Events.Bank.Config exposing (..) +import Events.Bank.Handlers.Login as BankLogin +import Game.Account.Finances.Models as Finances + + +events : Config msg -> String -> Finances.AccountId -> Router msg +events config requestId ( atmId, accNum ) name value = + case name of + "bank_login" -> + BankLogin.handler config.onBankLogin value + {- + "bank_account_updated" -> + config.fakeHandler (config.batchMsg []) value + "bank_account_removed" -> + config.fakeHandler (config.batchMsg []) value + "bank_login" -> + config.fakeHandler (config.batchMsg []) value + "bank_logout" -> + config.fakeHandler (config.batchMsg []) value + "bank_transfer_successful" -> + config.fakeHandler (config.batchMsg []) value + "bank_transfer_failed" -> + config.fakeHandler (config.batchMsg []) value + "bank_password_revealed" -> + config.fakeHandler (config.batchMsg []) value + -} + _ -> + Err "This channel is not implemented yet." diff --git a/src/Events/Bank/Handlers/Login.elm b/src/Events/Bank/Handlers/Login.elm new file mode 100644 index 00000000..96be8410 --- /dev/null +++ b/src/Events/Bank/Handlers/Login.elm @@ -0,0 +1,13 @@ +module Events.Bank.Handlers.Login exposing (Data, handler) + +import Json.Decode exposing (decodeValue) +import Decoders.Bank exposing (..) +import Events.Shared exposing (Handler) +import Game.Account.Finances.Models exposing (..) + +type alias Data = + (AccountId, Int, String) + +handler : Handler Data msg +handler toMsg = + decodeValue bankLogin >> Result.map toMsg \ No newline at end of file diff --git a/src/Events/Config.elm b/src/Events/Config.elm index 651be9b2..9021b565 100644 --- a/src/Events/Config.elm +++ b/src/Events/Config.elm @@ -3,10 +3,12 @@ module Events.Config exposing (..) import Events.Account.Config as Account import Events.Server.Config as Server import Events.BackFlix.Config as BackFlix +import Events.Bank.Config as Bank type alias Config msg = { forAccount : Account.Config msg , forServer : Server.Config msg , forBackFlix : BackFlix.Config msg + , forBank : Bank.Config msg } diff --git a/src/Events/Handler.elm b/src/Events/Handler.elm index 9114e415..7e679ad2 100644 --- a/src/Events/Handler.elm +++ b/src/Events/Handler.elm @@ -4,6 +4,7 @@ import Json.Decode exposing (Value) import Driver.Websocket.Channels as Ws import Events.Account.Handler as Account import Events.Server.Handler as Server +import Events.Bank.Handler as Bank import Events.BackFlix.Handler as BackFlix import Events.Config exposing (..) @@ -66,5 +67,8 @@ router config channel requestId event json = Ws.ServerChannel id -> Server.events config.forServer requestId id event json + Ws.BankChannel bankAccId _ -> + Bank.events config.forBank requestId bankAccId event json + Ws.BackFlixChannel -> BackFlix.events config.forBackFlix requestId event json diff --git a/src/Game/Account/Config.elm b/src/Game/Account/Config.elm index 87372449..2a427c6e 100644 --- a/src/Game/Account/Config.elm +++ b/src/Game/Account/Config.elm @@ -8,11 +8,10 @@ import Game.Account.Messages exposing (..) import Game.Account.Bounces.Config as Bounces import Game.Account.Database.Config as Database import Game.Account.Database.Models as Database -import Game.Account.Finances.Requests.Login as BankLoginRequest -import Game.Account.Finances.Requests.Transfer as BankTransferRequest import Game.Account.Finances.Config as Finances import Game.Account.Notifications.Config as Notifications import Game.Account.Notifications.Shared as Notifications +import Game.Bank.Config as Bank import Game.Meta.Types.Desktop.Apps exposing (Requester) import Game.Servers.Shared exposing (CId) import Game.Account.Bounces.Shared as Bounces @@ -30,10 +29,6 @@ type alias Config msg = , onError : Error -> msg , onSetEndpoint : CId -> Maybe CId -> msg - -- account.finances - , onBankAccountLogin : BankLoginRequest.Data -> Requester -> msg - , onBankAccountTransfer : BankTransferRequest.Data -> Requester -> msg - -- account.bounces , onReloadBounce : Bounces.ID -> String -> msg , onReloadIfBounceLoaded : Bounces.ID -> msg @@ -48,8 +43,6 @@ financesConfig accountId config = { flags = config.flags , toMsg = FinancesMsg >> config.toMsg , accountId = accountId - , onBankAccountLogin = config.onBankAccountLogin - , onBankAccountTransfer = config.onBankAccountTransfer } diff --git a/src/Game/Account/Database/Messages.elm b/src/Game/Account/Database/Messages.elm index 3fb494d3..89129feb 100644 --- a/src/Game/Account/Database/Messages.elm +++ b/src/Game/Account/Database/Messages.elm @@ -2,10 +2,12 @@ module Game.Account.Database.Messages exposing (Msg(..)) import Events.Account.Handlers.ServerPasswordAcquired as ServerPasswordAcquired import Events.Account.Handlers.VirusCollected as VirusCollected +import Game.Bank.Shared exposing (BankAccountData) import Game.Account.Database.Models exposing ( HackedBankAccountID , HackedBankAccount + , Password ) @@ -14,3 +16,5 @@ type Msg | HandleDatabaseAccountRemoved HackedBankAccountID | HandleDatabaseAccountUpdated HackedBankAccountID HackedBankAccount | HandleCollectedVirus VirusCollected.Data + | HandleDatabaseAccountLoggedIn HackedBankAccountID BankAccountData + | HandleDatabaseAccountPasswordAcquired HackedBankAccountID String diff --git a/src/Game/Account/Database/Models.elm b/src/Game/Account/Database/Models.elm index b4ba07b3..2c7c9c32 100644 --- a/src/Game/Account/Database/Models.elm +++ b/src/Game/Account/Database/Models.elm @@ -17,6 +17,10 @@ type alias AtmId = ID +type alias Token = + String + + --Sigma Viruses xD @@ -31,6 +35,10 @@ type VirusType | BTCMiner +type alias Password = + String + + type alias Virus = { name : String , version : Float diff --git a/src/Game/Account/Database/Update.elm b/src/Game/Account/Database/Update.elm index fba344b8..7984720d 100644 --- a/src/Game/Account/Database/Update.elm +++ b/src/Game/Account/Database/Update.elm @@ -27,6 +27,12 @@ update config msg model = HandleDatabaseAccountUpdated id account -> onHandleDatabaseAccountUpdated id account model + HandleDatabaseAccountLoggedIn _ _ -> + React.update model + + HandleDatabaseAccountPasswordAcquired _ _ -> + React.update model + HandleCollectedVirus data -> onHandleCollectedVirus config data model diff --git a/src/Game/Account/Finances/Config.elm b/src/Game/Account/Finances/Config.elm index 8d0a0f60..608bb936 100644 --- a/src/Game/Account/Finances/Config.elm +++ b/src/Game/Account/Finances/Config.elm @@ -3,8 +3,6 @@ module Game.Account.Finances.Config exposing (Config) import Core.Flags as Core import Game.Meta.Types.Desktop.Apps exposing (Requester) import Game.Account.Models as Account -import Game.Account.Finances.Requests.Login as LoginRequest -import Game.Account.Finances.Requests.Transfer as TransferRequest import Game.Account.Finances.Messages exposing (..) @@ -12,6 +10,4 @@ type alias Config msg = { flags : Core.Flags , toMsg : Msg -> msg , accountId : Account.ID - , onBankAccountLogin : LoginRequest.Data -> Requester -> msg - , onBankAccountTransfer : TransferRequest.Data -> Requester -> msg } diff --git a/src/Game/Account/Finances/Messages.elm b/src/Game/Account/Finances/Messages.elm index 48152990..b84b795f 100644 --- a/src/Game/Account/Finances/Messages.elm +++ b/src/Game/Account/Finances/Messages.elm @@ -1,15 +1,9 @@ module Game.Account.Finances.Messages exposing (..) import Game.Meta.Types.Desktop.Apps exposing (Requester) -import Game.Account.Finances.Requests.Login as LoginRequest -import Game.Account.Finances.Requests.Transfer as TransferRequest import Game.Account.Finances.Models exposing (..) type Msg - = LoginRequest Requester LoginRequest.Data - | TransferRequest Requester TransferRequest.Data - | HandleBankAccountClosed AccountId + = HandleBankAccountClosed AccountId | HandleBankAccountUpdated AccountId BankAccount - | HandleBankAccountLogin LoginRequest.Payload Requester - | HandleBankAccountTransfer TransferRequest.Payload Requester diff --git a/src/Game/Account/Finances/Models.elm b/src/Game/Account/Finances/Models.elm index 32de100f..1931cfc3 100644 --- a/src/Game/Account/Finances/Models.elm +++ b/src/Game/Account/Finances/Models.elm @@ -38,6 +38,13 @@ type alias BankAccount = } +type alias BankTransfer = + { from : AccountId + , to : AccountId + , value : Int + } + + type alias BitcoinAddress = String diff --git a/src/Game/Account/Finances/Requests/Login.elm b/src/Game/Account/Finances/Requests/Login.elm deleted file mode 100644 index cd5ea798..00000000 --- a/src/Game/Account/Finances/Requests/Login.elm +++ /dev/null @@ -1,69 +0,0 @@ -module Game.Account.Finances.Requests.Login - exposing - ( Payload - , Data - , loginRequest - ) - -import Json.Encode as Encode -import Json.Decode exposing (Value, decodeValue) -import Decoders.Bank exposing (accountData) -import Requests.Requests as Requests exposing (report) -import Requests.Topics as Topics -import Requests.Types exposing (FlagsSource, Code(..)) -import Game.Account.Models as Account -import Game.Meta.Types.Network as Network -import Game.Account.Finances.Shared exposing (BankAccountData) -import Game.Account.Finances.Models as Finances exposing (AccountNumber) - - -type alias Payload = - { bank : Network.NIP - , accountNum : AccountNumber - , password : String - } - - -type alias Data = - Result Error BankAccountData - - -type Error - = Invalid - | Unknown - - -loginRequest : Payload -> Account.ID -> FlagsSource a -> Cmd Data -loginRequest payload accountId flagsSrc = - flagsSrc - |> Requests.request (Topics.bankLogin accountId) - (encoder payload) - |> Cmd.map (uncurry <| receiver flagsSrc) - - - --- internals - - -encoder : Payload -> Value -encoder { bank, accountNum, password } = - Encode.object - [ ( "bank_net", Encode.string (Network.getId bank) ) - , ( "bank_ip", Encode.string (Network.getIp bank) ) - , ( "account", Encode.int accountNum ) - , ( "password", Encode.string password ) - ] - - -receiver : FlagsSource a -> Code -> Value -> Data -receiver flagsSrc code value = - case code of - OkCode -> - value - |> decodeValue accountData - |> report "Finances.Login" code flagsSrc - |> Result.mapError (always Unknown) - - _ -> - --TODO: Threat this error properly - Err Invalid diff --git a/src/Game/Account/Finances/Requests/Transfer.elm b/src/Game/Account/Finances/Requests/Transfer.elm deleted file mode 100644 index c2d7c1e8..00000000 --- a/src/Game/Account/Finances/Requests/Transfer.elm +++ /dev/null @@ -1,67 +0,0 @@ -module Game.Account.Finances.Requests.Transfer - exposing - ( Payload - , Data - , transferRequest - ) - -import Json.Encode as Encode exposing (Value) -import Requests.Requests as Requests -import Requests.Topics as Topics -import Requests.Types exposing (FlagsSource, Code(..)) -import Game.Account.Models as Account -import Game.Meta.Types.Network as Network -import Game.Account.Finances.Models as Finances exposing (AccountNumber) - - -type alias Payload = - { fromBank : Network.NIP - , fromAcc : AccountNumber - , toBank : Network.NIP - , toAcc : AccountNumber - , password : String - , value : Int - } - - -type alias Data = - Result () () - - -transferRequest : - Payload - -> Account.ID - -> FlagsSource a - -> Cmd Data -transferRequest payload accountId flagsSrc = - flagsSrc - |> Requests.request (Topics.bankTransfer accountId) (encoder payload) - |> Cmd.map (uncurry receiver) - - - --- internals - - -encoder : Payload -> Value -encoder { fromBank, fromAcc, toBank, toAcc, password, value } = - Encode.object - [ ( "from_bank_net", Encode.string (Network.getId fromBank) ) - , ( "from_bank_ip", Encode.string (Network.getIp fromBank) ) - , ( "from_acc", Encode.int fromAcc ) - , ( "to_bank_net", Encode.string (Network.getId toBank) ) - , ( "to_bank_ip", Encode.string (Network.getIp toBank) ) - , ( "to_acc", Encode.int toAcc ) - , ( "password", Encode.string password ) - , ( "value", Encode.int value ) - ] - - -receiver : Code -> Value -> Data -receiver code value = - case code of - OkCode -> - Ok () - - _ -> - Err () diff --git a/src/Game/Account/Finances/Shared.elm b/src/Game/Account/Finances/Shared.elm deleted file mode 100644 index 2660f9d4..00000000 --- a/src/Game/Account/Finances/Shared.elm +++ /dev/null @@ -1,24 +0,0 @@ -module Game.Account.Finances.Shared exposing (..) - - -type alias BankAccountData = - { balance : Int - } - - -toMoney : Int -> String -toMoney value = - let - str = - toString value - - ( dolars, cents ) = - ( String.dropRight 2 str, String.right 2 str ) - - formatedStr = - if String.length dolars > 0 then - dolars ++ "." ++ cents - else - "0." ++ cents - in - formatedStr diff --git a/src/Game/Account/Finances/Update.elm b/src/Game/Account/Finances/Update.elm index c37fef9b..33f03f76 100644 --- a/src/Game/Account/Finances/Update.elm +++ b/src/Game/Account/Finances/Update.elm @@ -2,8 +2,6 @@ module Game.Account.Finances.Update exposing (update) import Utils.React as React exposing (React) import Game.Meta.Types.Desktop.Apps exposing (Requester) -import Game.Account.Finances.Requests.Login as LoginRequest exposing (loginRequest) -import Game.Account.Finances.Requests.Transfer as TransferRequest exposing (transferRequest) import Game.Account.Finances.Config exposing (..) import Game.Account.Finances.Models exposing (..) import Game.Account.Finances.Messages exposing (..) @@ -22,18 +20,6 @@ update config msg model = HandleBankAccountUpdated accountId account -> handleBankAccountUpdated accountId account model - HandleBankAccountLogin payload requester -> - handleBankAccountLogin config payload requester model - - HandleBankAccountTransfer payload requester -> - handleBankAccountTransfer config payload requester model - - LoginRequest requester data -> - onLoginRequest config requester data model - - TransferRequest requester data -> - onTransferRequest config requester data model - handleBankAccountClosed : AccountId -> Model -> UpdateResponse msg handleBankAccountClosed accountId model = @@ -43,57 +29,3 @@ handleBankAccountClosed accountId model = handleBankAccountUpdated : AccountId -> BankAccount -> Model -> UpdateResponse msg handleBankAccountUpdated accountId bankAccount model = ( insertBankAccount accountId bankAccount model, React.none ) - - -handleBankAccountLogin : - Config msg - -> LoginRequest.Payload - -> Requester - -> Model - -> UpdateResponse msg -handleBankAccountLogin config payload requester model = - let - request_ = - config - |> loginRequest payload config.accountId - |> Cmd.map (LoginRequest requester >> config.toMsg) - |> React.cmd - in - ( model, request_ ) - - -handleBankAccountTransfer : - Config msg - -> TransferRequest.Payload - -> Requester - -> Model - -> UpdateResponse msg -handleBankAccountTransfer config payload requester model = - let - request_ = - config - |> transferRequest payload config.accountId - |> Cmd.map (TransferRequest requester >> config.toMsg) - |> React.cmd - in - ( model, request_ ) - - -onLoginRequest : - Config msg - -> Requester - -> LoginRequest.Data - -> Model - -> UpdateResponse msg -onLoginRequest config requester data model = - ( model, React.msg <| config.onBankAccountLogin data requester ) - - -onTransferRequest : - Config msg - -> Requester - -> TransferRequest.Data - -> Model - -> UpdateResponse msg -onTransferRequest config requester data model = - ( model, React.msg <| config.onBankAccountTransfer data requester ) diff --git a/src/Game/Bank/Config.elm b/src/Game/Bank/Config.elm new file mode 100644 index 00000000..96c41461 --- /dev/null +++ b/src/Game/Bank/Config.elm @@ -0,0 +1,38 @@ +module Game.Bank.Config exposing (..) + +import Core.Flags as Core +import Json.Decode exposing (Value) +import Game.Account.Database.Models + exposing + ( HackedBankAccountID + , HackedBankAccount + ) +import Game.Account.Finances.Models as Finances + exposing + ( AccountId + , BankAccount + ) +import Game.Bank.Messages exposing (Msg) +import Game.Meta.Types.Desktop.Apps exposing (Requester) +import Game.Servers.Shared exposing (..) +import Game.Shared exposing (..) + + +type alias Config msg = + { flags : Core.Flags + , toMsg : Msg -> msg + , batchMsg : List msg -> msg + , finances : Finances.Model + , awaitEvent : String -> ( String, msg ) -> msg + , accountId : ID + , activeGatewayCId : Maybe CId + , activeBounce : Maybe ID + , onLogin : AccountId -> String -> Value -> msg + , onLogout : AccountId -> String -> msg + , onSendSessionId : String -> Requester -> msg + , onHackedBankAccountUpdated : + HackedBankAccountID + -> HackedBankAccount + -> msg + , onBankAccountUpdated : AccountId -> BankAccount -> msg + } diff --git a/src/Game/Bank/Messages.elm b/src/Game/Bank/Messages.elm new file mode 100644 index 00000000..f87c5833 --- /dev/null +++ b/src/Game/Bank/Messages.elm @@ -0,0 +1,25 @@ +module Game.Bank.Messages exposing (Msg(..)) + +import Json.Decode exposing (Value) +import Game.Account.Finances.Models exposing (AccountId, AtmId, AccountNumber) +import Game.Bank.Shared exposing (BankAccountData) +import Game.Meta.Types.Desktop.Apps exposing (Requester) +import Game.Meta.Types.Network exposing (IP) + + +type + Msg + -- TODO: push BounceId, ServerId, AccountId on config + = HandleLogin AccountId String Requester + | HandleLoginToken AccountId String Requester + | HandleJoinedBank String Value + | HandleCreateAccount AtmId Requester + -- the first String Parameter is for SessionId + | HandleCloseAccount String Requester + | HandleChangePassword String Requester + | HandleTransfer String IP AccountNumber Int Requester + | HandleRevealPassword String String Requester + | HandleResync String Requester + | HandleLogout String Requester + | HandleLoggedIn AccountId Int String + | UpdateCache String BankAccountData diff --git a/src/Game/Bank/Models.elm b/src/Game/Bank/Models.elm new file mode 100644 index 00000000..81fc4b5f --- /dev/null +++ b/src/Game/Bank/Models.elm @@ -0,0 +1,86 @@ +module Game.Bank.Models exposing (..) + +import Dict as Dict exposing (Dict) +import Random.Pcg as Random +import Utils.Maybe as Maybe +import Decoders.Bank as Bank +import Game.Account.Finances.Models exposing (AtmId, AccountNumber, AccountId) +import Game.Bank.Shared exposing (BankAccountData) + + +type alias Model = + { sessions : BankSessions + , randomUuidSeed : Random.Seed + , waiters : Dict String AccountId + } + + +type alias BankSessions = + Dict String BankSession + + +type alias BankSession = + { atmId : AtmId + , accountNumber : AccountNumber + , accountCache : BankAccountData + } + + +initialModel : Model +initialModel = + Model Dict.empty (Random.initialSeed 8589869056) Dict.empty + + +getAccountId : String -> Model -> Maybe AccountId +getAccountId id model = + let + session = + getSession id model + + atmId = + Maybe.map .atmId session + + accountNumber = + Maybe.map .accountNumber session + + accountId = + Maybe.uncurry atmId accountNumber + in + accountId + + +getSession : String -> Model -> Maybe BankSession +getSession id = + .sessions >> Dict.get id + + +endSession : String -> Model -> Model +endSession id model = + { model | sessions = Dict.remove id model.sessions } + + +addWaitingId : String -> AccountId -> Model -> Model +addWaitingId rId id model = + { model | waiters = Dict.insert rId id model.waiters } + + +startNewSession : + String + -> BankAccountData + -> Model + -> Model +startNewSession rId data model = + let + waitingId = + Dict.get rId model.waiters + in + case Debug.log "waiting for ID: " waitingId of + Just ( atmId, accNum ) -> + insertSession model rId (BankSession atmId accNum data) + Nothing -> + model + + +insertSession : Model -> String -> BankSession -> Model +insertSession model rId session = + { model | sessions = Dict.insert rId session model.sessions } diff --git a/src/Game/Bank/Requests/ChangePassword.elm b/src/Game/Bank/Requests/ChangePassword.elm new file mode 100644 index 00000000..afa69a72 --- /dev/null +++ b/src/Game/Bank/Requests/ChangePassword.elm @@ -0,0 +1,67 @@ +module Game.Bank.Requests.ChangePassword exposing (changePasswordRequest, Data) + +import Utils.Json.Decode exposing (commonError, message) +import Json.Decode as Decode exposing (Decoder, decodeValue, succeed, fail) +import Json.Encode as Encode exposing (Value) +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Requests.Topics as Topics +import Requests.Requests as Requests exposing (report) +import Game.Account.Finances.Models exposing (AccountId) +import Game.Bank.Shared exposing (..) + +type alias Data = + Result ChangePassError () + + +changePasswordRequest : + AccountId + -> String + -> FlagsSource a + -> Cmd Data +changePasswordRequest id requestId flagsSrc = + flagsSrc + |> Requests.request (Topics.bankChangePass id requestId) emptyPayload + |> Cmd.map (uncurry <| receiver flagsSrc) + + +-- internals + + +errorToString : ChangePassError -> String +errorToString error = + case error of + CPBadRequest -> + "Bad Request" + + CPBankAccountNotBelongs -> + "You don't own this account." + + +errorMessage : Decoder ChangePassError +errorMessage = + message <| + \str -> + case str of + "bad_request" -> + succeed CPBadRequest + + "bank_account_not_belongs" -> + succeed CPBankAccountNotBelongs + + value -> + commonError "bank account change password error message" value + |> fail + + +receiver : FlagsSource a -> Code -> Value -> Data +receiver flagsSrc code value = + case code of + OkCode -> + Ok () + + _ -> + value + |> decodeValue errorMessage + |> report "Bank.ChangePass" code flagsSrc + |> Result.mapError (always CPBadRequest) + |> Result.andThen Err diff --git a/src/Game/Bank/Requests/CloseAccount.elm b/src/Game/Bank/Requests/CloseAccount.elm new file mode 100644 index 00000000..4537dfd6 --- /dev/null +++ b/src/Game/Bank/Requests/CloseAccount.elm @@ -0,0 +1,78 @@ +module Game.Bank.Requests.CloseAccount exposing (closeAccountRequest, Data) + +import Utils.Json.Decode exposing (commonError, message) +import Json.Decode as Decode exposing (Decoder, decodeValue, succeed, fail) +import Json.Encode as Encode exposing (Value) +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Requests.Topics as Topics +import Requests.Requests as Requests exposing (report) +import Game.Account.Models exposing (..) +import Game.Account.Finances.Models exposing (AccountId) +import Game.Bank.Shared exposing (..) +import Game.Account.Database.Models as Database +import Game.Meta.Types.Network as Network + + +type alias Data = + Result CloseAccountError () + + +closeAccountRequest : + AccountId + -> String + -> FlagsSource a + -> Cmd Data +closeAccountRequest id requestId flagsSrc = + flagsSrc + |> Requests.request (Topics.bankCloseAcc id requestId) emptyPayload + |> Cmd.map (uncurry <| receiver flagsSrc) + + + +-- internals + + +errorToString : CloseAccountError -> String +errorToString error = + case error of + ClAccBadRequest -> + "Bad Request" + + ClAccBankAccountNotBelongs -> + "You don't own this account." + + ClAccBankAccountNotEmpty -> + "You can't close this account because it's not empty." + + +errorMessage : Decoder CloseAccountError +errorMessage = + message <| + \str -> + case str of + "bad_request" -> + succeed ClAccBadRequest + + "bank_account_not_belongs" -> + succeed ClAccBankAccountNotBelongs + + "bank_account_not_empty" -> + succeed ClAccBankAccountNotEmpty + + value -> + commonError "bank account close error message" value + |> fail + + +receiver : FlagsSource a -> Code -> Value -> Data +receiver flagsSrc code value = + case code of + OkCode -> + Ok () + + _ -> + value + |> decodeValue errorMessage + |> report "Bank.CloseAcc" code flagsSrc + |> Result.mapError (always ClAccBadRequest) + |> Result.andThen Err diff --git a/src/Game/Bank/Requests/CreateAccount.elm b/src/Game/Bank/Requests/CreateAccount.elm new file mode 100644 index 00000000..8088162e --- /dev/null +++ b/src/Game/Bank/Requests/CreateAccount.elm @@ -0,0 +1,86 @@ +module Game.Bank.Requests.CreateAccount exposing (createAccountRequest, Data) + +import Utils.Json.Decode exposing (commonError, message) +import Json.Decode as Decode exposing (Decoder, decodeValue, succeed, fail) +import Json.Encode as Encode exposing (Value) +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Requests.Topics as Topics +import Requests.Requests as Requests exposing (report) +import Game.Account.Models exposing (..) +import Game.Account.Finances.Models exposing (AtmId) +import Game.Bank.Shared exposing (..) +import Game.Servers.Shared exposing (..) + + +type alias Data = + Result CreateAccountError () + + +createAccountRequest : + ID + -> AtmId + -> CId + -> FlagsSource a + -> Cmd Data +createAccountRequest id atmId cid flagsSrc = + flagsSrc + |> Requests.request (Topics.accountBankCreateAcc id) + (encoder atmId cid) + |> Cmd.map (uncurry <| receiver flagsSrc) + + +encoder : AtmId -> CId -> Value +encoder atmId cid = + case cid of + GatewayCId serverId -> + Encode.object + [ ( "atm_id", Encode.string atmId ) + , ( "gateway", Encode.string serverId ) + ] + + _ -> + emptyPayload + + + +-- internals + + +errorToString : CreateAccountError -> String +errorToString error = + case error of + CrAccBadRequest -> + "Bad Request" + + CrAccServerNotBelongs -> + "You can't create this account because the server is not yours." + + +errorMessage : Decoder CreateAccountError +errorMessage = + message <| + \str -> + case str of + "bad_request" -> + succeed CrAccBadRequest + + "server_not_belongs" -> + succeed CrAccServerNotBelongs + + value -> + commonError "bank account create error message" value + |> fail + + +receiver : FlagsSource a -> Code -> Value -> Data +receiver flagsSrc code value = + case code of + OkCode -> + Ok () + + _ -> + value + |> decodeValue errorMessage + |> report "Bank.CreateAcc" code flagsSrc + |> Result.mapError (always CrAccBadRequest) + |> Result.andThen Err diff --git a/src/Game/Bank/Requests/Logout.elm b/src/Game/Bank/Requests/Logout.elm new file mode 100644 index 00000000..cedc48cf --- /dev/null +++ b/src/Game/Bank/Requests/Logout.elm @@ -0,0 +1,63 @@ +module Game.Bank.Requests.Logout exposing (logoutRequest, Data) + +import Utils.Json.Decode exposing (commonError, message) +import Json.Decode as Decode exposing (Decoder, decodeValue, succeed, fail) +import Json.Encode as Encode exposing (Value) +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Requests.Topics as Topics +import Requests.Requests as Requests exposing (report) +import Game.Account.Finances.Models exposing (AccountId) +import Game.Bank.Shared exposing (..) + + +type alias Data = + Result LogoutError () + + +logoutRequest : + AccountId + -> String + -> FlagsSource a + -> Cmd Data +logoutRequest id requestId flagsSrc = + flagsSrc + |> Requests.request (Topics.bankLogout id requestId) emptyPayload + |> Cmd.map (uncurry <| receiver flagsSrc) + + + +-- internals + + +errorToString : LogoutError -> String +errorToString error = + case error of + LOBadRequest -> + "Bad Request" + + +errorMessage : Decoder LogoutError +errorMessage = + message <| + \str -> + case str of + "bad_request" -> + succeed LOBadRequest + + value -> + commonError "bank account logout error message" value + |> fail + + +receiver : FlagsSource a -> Code -> Value -> Data +receiver flagsSrc code value = + case code of + OkCode -> + Ok () + + _ -> + value + |> decodeValue errorMessage + |> report "Bank.Logout" code flagsSrc + |> Result.mapError (always LOBadRequest) + |> Result.andThen Err diff --git a/src/Game/Bank/Requests/Resync.elm b/src/Game/Bank/Requests/Resync.elm new file mode 100644 index 00000000..001b7868 --- /dev/null +++ b/src/Game/Bank/Requests/Resync.elm @@ -0,0 +1,46 @@ +module Game.Bank.Requests.Resync exposing (Data, resyncRequest) + +import Time exposing (Time) +import Json.Decode as Decode exposing (Value, decodeValue) +import Requests.Requests as Requests exposing (report) +import Requests.Topics as Topics +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Decoders.Bank as Decoder +import Game.Account.Finances.Models exposing (AccountId) +import Game.Bank.Shared exposing (BankAccountData) +import Game.Servers.Shared exposing (..) + + +type alias Data = + Result () ( AccountId, BankAccountData ) + + +resyncRequest : AccountId -> String -> FlagsSource a -> Cmd Data +resyncRequest id requestId flagsSrc = + flagsSrc + |> Requests.request (Topics.bankResync id requestId) + emptyPayload + |> Cmd.map (uncurry <| receiver flagsSrc id) + + + +-- internals + + +receiver : + FlagsSource a + -> AccountId + -> Code + -> Value + -> Data +receiver flagsSrc accountId code value = + case code of + OkCode -> + value + |> decodeValue Decoder.accountData + |> report "Bank.Resync" code flagsSrc + |> Result.map ((,) accountId) + |> Result.mapError (always ()) + + _ -> + Err () diff --git a/src/Game/Bank/Requests/RevealPassword.elm b/src/Game/Bank/Requests/RevealPassword.elm new file mode 100644 index 00000000..63d977c6 --- /dev/null +++ b/src/Game/Bank/Requests/RevealPassword.elm @@ -0,0 +1,83 @@ +module Game.Bank.Requests.RevealPassword exposing (revealPasswordRequest, Data) + +import Utils.Json.Decode exposing (commonError, message) +import Json.Decode as Decode exposing (Decoder, decodeValue, succeed, fail) +import Json.Encode as Encode exposing (Value) +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Requests.Topics as Topics +import Requests.Requests as Requests exposing (report) +import Game.Account.Database.Models exposing (Token) +import Game.Account.Finances.Models exposing (AtmId) +import Game.Bank.Shared exposing (..) +import Game.Servers.Shared exposing (..) + + +type alias Data = + Result RevealPasswordError () + + +revealPasswordRequest : + CId + -> Token + -> FlagsSource a + -> Cmd Data +revealPasswordRequest cid token flagsSrc = + flagsSrc + |> Requests.request (Topics.bankRevealPass cid) + (encoder token) + |> Cmd.map (uncurry <| receiver flagsSrc) + + +encoder : Token -> Value +encoder token = + Encode.object [ ( "token", Encode.string token ) ] + + + +-- internals + + +errorToString : RevealPasswordError -> String +errorToString error = + case error of + RPBadRequest -> + "Bad Request" + + RPTokenInvalid -> + "You can't use this token because it is invalid." + + RPTokenExpired -> + "You can`t use this token because it is expired." + + +errorMessage : Decoder RevealPasswordError +errorMessage = + message <| + \str -> + case str of + "bad_request" -> + succeed RPBadRequest + + "token_expired" -> + succeed RPTokenExpired + + "token_invalid" -> + succeed RPTokenInvalid + + value -> + commonError "reveal bank account password error message" value + |> fail + + +receiver : FlagsSource a -> Code -> Value -> Data +receiver flagsSrc code value = + case code of + OkCode -> + Ok () + + _ -> + value + |> decodeValue errorMessage + |> report "Bank.RevealPass" code flagsSrc + |> Result.mapError (always RPBadRequest) + |> Result.andThen Err diff --git a/src/Game/Bank/Requests/Transfer.elm b/src/Game/Bank/Requests/Transfer.elm new file mode 100644 index 00000000..037d52d7 --- /dev/null +++ b/src/Game/Bank/Requests/Transfer.elm @@ -0,0 +1,102 @@ +module Game.Bank.Requests.Transfer exposing (transferRequest, Data) + +import Utils.Json.Decode exposing (commonError, message) +import Json.Decode as Decode exposing (Decoder, decodeValue, succeed, fail) +import Json.Encode as Encode exposing (Value) +import Requests.Types exposing (FlagsSource, Code(..), emptyPayload) +import Requests.Topics as Topics +import Requests.Requests as Requests exposing (report) +import Game.Account.Models exposing (..) +import Game.Account.Database.Models exposing (Token) +import Game.Account.Finances.Models exposing (AccountId, AtmId, AccountNumber) +import Game.Bank.Shared exposing (..) +import Game.Meta.Types.Network exposing (IP) +import Game.Servers.Shared exposing (..) + + +type alias Data = + Result TransferError () + + +transferRequest : + AccountId + -> String + -> AccountNumber + -> IP + -> Int + -> FlagsSource a + -> Cmd Data +transferRequest id requestId acc ip amount flagsSrc = + flagsSrc + |> Requests.request (Topics.bankTransfer id requestId) + (encoder acc ip amount) + |> Cmd.map (uncurry <| receiver flagsSrc) + + +encoder : AccountNumber -> IP -> Int -> Value +encoder account ip amount = + Encode.object + [ ( "to_acc", Encode.int account ) + , ( "to_bank_net", Encode.string "::" ) + , ( "to_bank_ip", Encode.string ip ) + , ( "amount", Encode.int amount ) + ] + + + +-- internals + + +errorToString : TransferError -> String +errorToString error = + case error of + TFBadRequest -> + "Bad Request" + + TFNotABank -> + "You can't transfer because the given ip is not a bank." + + TFNotEnoughFunds -> + "You can't transfer because you don't have enough funds" + + TFAccountNotExists -> + "You can`t transfer because the destiny account do not exist." + + +errorMessage : Decoder TransferError +errorMessage = + message <| + \str -> + case str of + "bad_request" -> + succeed TFBadRequest + + "nip_not_found" -> + succeed TFNotABank + + "atm_not_a_bank" -> + succeed TFNotABank + + "bank_account_not_found" -> + succeed TFAccountNotExists + + "bank_account_no_funds" -> + succeed TFNotEnoughFunds + + value -> + commonError "reveal bank account password error message" value + |> fail + + +receiver : FlagsSource a -> Code -> Value -> Data +receiver flagsSrc code value = + case code of + OkCode -> + Ok () + + _ -> + value + |> decodeValue errorMessage + |> report "Bank.RevealPass" code flagsSrc + |> Result.mapError (always TFBadRequest) + |> Result.andThen Err diff --git a/src/Game/Bank/Shared.elm b/src/Game/Bank/Shared.elm new file mode 100644 index 00000000..bcbc3f39 --- /dev/null +++ b/src/Game/Bank/Shared.elm @@ -0,0 +1,57 @@ +module Game.Bank.Shared exposing (..) + + +type alias BankAccountData = + { balance : Int + } + + +type ChangePassError + = CPBankAccountNotBelongs + | CPBadRequest + + +type CloseAccountError + = ClAccBankAccountNotBelongs + | ClAccBankAccountNotEmpty + | ClAccBadRequest + + +type CreateAccountError + = CrAccBadRequest + | CrAccServerNotBelongs + + +type RevealPasswordError + = RPBadRequest + | RPTokenInvalid + | RPTokenExpired + + +type TransferError + = TFBadRequest + | TFNotABank + | TFNotEnoughFunds + | TFAccountNotExists + + +type LogoutError + = LOBadRequest + + +toMoney : Int -> String +toMoney value = + let + str = + toString value + + ( dolars, cents ) = + ( String.dropRight 2 str, String.right 2 str ) + + formatedStr = + if String.length dolars > 0 then + dolars ++ "." ++ cents + else + "0." ++ cents + in + formatedStr diff --git a/src/Game/Bank/Update.elm b/src/Game/Bank/Update.elm new file mode 100644 index 00000000..658d16ba --- /dev/null +++ b/src/Game/Bank/Update.elm @@ -0,0 +1,413 @@ +module Game.Bank.Update exposing (update) + +import Json.Encode as Encode exposing (Value) +import Json.Decode exposing (decodeValue) +import Dict as Dict +import Time exposing (Time) +import Task exposing (..) +import Utils.React as React exposing (React) +import Utils.Model.RandomUuid as Random +import Decoders.Bank as Decoder +import Game.Account.Finances.Models as Finances + exposing + (AccountId + , AtmId + , AccountNumber + ) +import Game.Account.Database.Models exposing (Token) +import Game.Bank.Config exposing (..) +import Game.Bank.Models exposing (..) +import Game.Bank.Messages exposing (..) +import Game.Bank.Requests.CreateAccount as CreateAccountRequest +import Game.Bank.Requests.CloseAccount as CloseAccountRequest +import Game.Bank.Requests.Resync as ResyncRequest +import Game.Bank.Requests.Transfer as TransferRequest +import Game.Bank.Requests.ChangePassword as ChangePasswordRequest +import Game.Bank.Requests.RevealPassword as RevealPasswordRequest +import Game.Bank.Requests.Logout as LogoutRequest +import Game.Meta.Types.Desktop.Apps exposing (Requester) +import Game.Meta.Types.Network exposing (IP) +import Game.Servers.Shared exposing (CId(..)) + + +type alias UpdateResponse msg = + ( Model, React msg ) + + +update : + Config msg + -> Msg + -> Model + -> UpdateResponse msg +update config msg model = + case msg of + HandleLogin accountId password requester -> + handleLogin config accountId password requester model + + HandleLoginToken accountId token requester -> + handleLoginToken config accountId token requester model + + HandleLoggedIn accountId balance password -> + handleLoggedIn config accountId balance password model + + HandleJoinedBank requestId data -> + handleJoinedBank config requestId data model + + HandleCreateAccount atmId requester -> + handleCreateAccount config atmId requester model + + HandleCloseAccount sessionId requester -> + handleCloseAccount config sessionId requester model + + HandleChangePassword sessionId requester -> + handleChangePassword config sessionId requester model + + HandleTransfer sessionId targetBank targetAcc value requester -> + handleTransfer config sessionId targetBank targetAcc value requester model + + HandleRevealPassword sessionId token requester -> + handleRevealPassword config sessionId token requester model + + HandleResync sessionId requester -> + handleResync config sessionId requester model + + HandleLogout sessionId requester -> + handleLogout config sessionId requester model + + UpdateCache sessionId data -> + React.update model + + +handleLogin : + Config msg + -> AccountId + -> String + -> Requester + -> Model + -> UpdateResponse msg +handleLogin config bankAccId password requester model = + let + accountId = + config.accountId + + gatewayId = + config.activeGatewayCId + + bounceId = + config.activeBounce + + ( model_, requestId ) = + Random.newUuid model + + model0 = + addWaitingId requestId bankAccId model_ + + ( atmId, accNum ) = + bankAccId + + react = + case gatewayId of + Just (GatewayCId serverId) -> + React.batch + config.batchMsg + [ config.onLogin bankAccId requestId (payload serverId) + |> React.msg + , loginMsg config requestId requester + |> loginEventReaction config requestId + ] + + _ -> + React.none + + payload serverId = + let + baseList = + [ ( "gateway_id", Encode.string serverId ) + , ( "entity_id", Encode.string accountId ) + , ( "password", Encode.string password ) + , ( "request_id", Encode.string requestId ) + ] + + list = + case bounceId of + Just bounceId -> + ( "bounce_id", Encode.string bounceId ) :: baseList + + Nothing -> + baseList + in + Encode.object list + in + ( model0, react ) + + +handleLoginToken : + Config msg + -> AccountId + -> String + -> Requester + -> Model + -> UpdateResponse msg +handleLoginToken config bankAccId token requester model = + let + accountId = + config.accountId + + gatewayId = + config.activeGatewayCId + + bounceId = + config.activeBounce + + ( model_, requestId ) = + Random.newUuid model + + ( atmId, accNum ) = + bankAccId + + react = + case gatewayId of + Just (GatewayCId serverId) -> + React.batch + config.batchMsg + [ config.onLogin bankAccId requestId (payload serverId) + |> React.msg + , loginMsg config requestId requester + |> loginEventReaction config requestId + ] + + _ -> + React.none + + payload serverId = + let + baseList = + [ ( "gateway_id", Encode.string serverId ) + , ( "entity_id", Encode.string accountId ) + , ( "token", Encode.string token ) + , ( "request_id", Encode.string requestId ) + ] + + list = + case bounceId of + Just bounceId -> + ( "bounce_id", Encode.string bounceId ) :: baseList + + Nothing -> + baseList + in + Encode.object list + in + ( model, react ) + +handleLoggedIn : + Config msg + -> AccountId + -> Int + -> String + -> Model + -> UpdateResponse msg +handleLoggedIn config accId balance pass model = + let + hackedBankAccount time = + { name = "Bank Louco" + , password = Just pass + , knownBalance = Just balance + , token = Nothing + , notes = Nothing + , lastLoginDate = Nothing + , lastUpdate = time + } + + onHackedBankAccount = + hackedBankAccount >> config.onHackedBankAccountUpdated accId + in + case Dict.get accId <| Finances.getBankAccounts config.finances of + Just _ -> + let + acc = + { name = "Bank Louco" + , password = pass + , balance = balance + } + in + (model, React.msg <| config.onBankAccountUpdated accId acc) + + Nothing -> + (model, React.cmd <| Task.perform onHackedBankAccount Time.now) + + + + + +handleJoinedBank : + Config msg + -> String + -> Value + -> Model + -> UpdateResponse msg +handleJoinedBank config requestId data model = + let + data_ = + decodeValue Decoder.accountData data + + model_ = + case data_ of + Ok data -> + startNewSession requestId data model + Err _ -> + model + in + React.update model_ + + +handleCreateAccount : + Config msg + -> AtmId + -> Requester + -> Model + -> UpdateResponse msg +handleCreateAccount ({ accountId } as config) atmId requester model = + let + request = + CreateAccountRequest.createAccountRequest + + callback cid = + config + |> request accountId atmId cid + |> React.cmd + |> React.map (\a -> config.batchMsg []) + in + React.maybeUpdate callback config.activeGatewayCId model + + +handleCloseAccount : + Config msg + -> String + -> Requester + -> Model + -> UpdateResponse msg +handleCloseAccount config sessionId requester model = + let + callback bankAccId = + CloseAccountRequest.closeAccountRequest bankAccId sessionId config + |> React.cmd + |> React.map (\a -> config.batchMsg []) + in + getAccIdAndRequest callback sessionId model + + +handleChangePassword : + Config msg + -> String + -> Requester + -> Model + -> UpdateResponse msg +handleChangePassword config sId requester model = + let + callback bankAccId = + ChangePasswordRequest.changePasswordRequest bankAccId sId config + |> React.cmd + |> React.map (\a -> config.batchMsg []) + in + getAccIdAndRequest callback sId model + + +handleTransfer : + Config msg + -> String + -> IP + -> AccountNumber + -> Int + -> Requester + -> Model + -> UpdateResponse msg +handleTransfer config sId bIp accNumber value requester model = + let + callback bId = + config + |> TransferRequest.transferRequest bId sId accNumber bIp value + |> React.cmd + |> React.map (\a -> config.batchMsg []) + in + getAccIdAndRequest callback sId model + + +handleRevealPassword : + Config msg + -> String + -> Token + -> Requester + -> Model + -> UpdateResponse msg +handleRevealPassword config sessionId token requester model = + let + callback cid = + RevealPasswordRequest.revealPasswordRequest cid token config + |> React.cmd + -- TODO: Enviar uma mensagem para o requester para ele poder + -- dar feedback visual + |> React.map (\a -> config.batchMsg []) + + session = + getSession sessionId model + in + case Maybe.map mapSessionToAccId session of + Just _ -> + React.maybeUpdate callback config.activeGatewayCId model + + Nothing -> + React.update model + + +handleResync : Config msg -> String -> Requester -> Model -> UpdateResponse msg +handleResync ({ toMsg } as config) sessionId requester model = + let + callback bankAccId = + ResyncRequest.resyncRequest bankAccId sessionId config + |> React.cmd + |> React.map (\a -> config.batchMsg []) + + --UpdateCache sessionId >> toMsg) + in + getAccIdAndRequest callback sessionId model + + +handleLogout : Config msg -> String -> Requester -> Model -> UpdateResponse msg +handleLogout config sessionId requester model = + let + callback bankAccId = + LogoutRequest.logoutRequest bankAccId sessionId config + |> React.cmd + |> React.map (\a -> config.onLogout bankAccId sessionId) + in + getAccIdAndRequest callback sessionId model + + +getAccIdAndRequest : + (AccountId -> React msg) + -> String + -> Model + -> UpdateResponse msg +getAccIdAndRequest callback sessionId model = + model + |> getSession sessionId + |> Maybe.map mapSessionToAccId + |> flip (React.maybeUpdate callback) model + + +loginEventReaction : Config msg -> String -> msg -> React msg +loginEventReaction config requestId msg = + ( "bank_login", msg ) + |> config.awaitEvent requestId + |> React.msg + + +loginMsg : Config msg -> String -> Requester -> msg +loginMsg { onSendSessionId, batchMsg } requestId requester = + onSendSessionId requestId requester + + +mapSessionToAccId : BankSession -> AccountId +mapSessionToAccId session = + ( session.atmId, session.accountNumber ) diff --git a/src/Game/Config.elm b/src/Game/Config.elm index a28bbba4..ba034225 100644 --- a/src/Game/Config.elm +++ b/src/Game/Config.elm @@ -7,14 +7,14 @@ import Core.Error as Error exposing (Error) import Game.Meta.Types.Context as Context import Game.Meta.Types.Desktop.Apps exposing (Requester) import Game.Account.Bounces.Shared as Bounces -import Game.Account.Finances.Requests.Login as BankLoginRequest -import Game.Account.Finances.Requests.Transfer as BankTransferRequest import Game.Account.Notifications.Shared as AccountNotifications import Game.Servers.Notifications.Shared as ServersNotifications import Game.Account.Config as Account import Game.Account.Models as Account import Game.Account.Messages as Account +import Game.Account.Finances.Models as Finances import Game.BackFlix.Config as BackFlix +import Game.Bank.Config as Bank import Game.Servers.Config as Servers import Game.Servers.Models as Servers import Game.Servers.Shared exposing (CId) @@ -32,6 +32,12 @@ type alias Config msg = , batchMsg : List msg -> msg , onJoinServer : CId -> Maybe Value -> msg , onError : Error -> msg + , awaitEvent : String -> ( String, msg ) -> msg + + -- bank + , onSendBankSessionId : String -> Requester -> msg + , onJoinBank : Finances.AccountId -> String -> Value -> msg + , onLeaveBank : Finances.AccountId -> String -> msg -- web , onJoinFailed : Requester -> msg @@ -50,10 +56,6 @@ type alias Config msg = -- account.bounces , onReloadBounce : Bounces.ID -> String -> msg , onReloadIfBounceLoaded : Bounces.ID -> msg - - -- account.finances - , onBankAccountLogin : BankLoginRequest.Data -> Requester -> msg - , onBankAccountTransfer : BankTransferRequest.Data -> Requester -> msg } @@ -111,8 +113,6 @@ accountConfig lastTick flags config = |> config.toMsg -- account.finances - , onBankAccountLogin = config.onBankAccountLogin - , onBankAccountTransfer = config.onBankAccountTransfer , onReloadBounce = config.onReloadBounce , onReloadIfBounceLoaded = config.onReloadIfBounceLoaded , onToast = config.onAccountToast @@ -137,6 +137,33 @@ webConfig flags servers config = } +bankConfig : + Account.Model + -> Servers.Model + -> Core.Flags + -> Config msg + -> Bank.Config msg +bankConfig account servers flags config = + { flags = flags + , toMsg = BankMsg >> config.toMsg + , batchMsg = config.batchMsg + , accountId = Account.getId account + , finances = Account.getFinances account + , activeGatewayCId = Account.getGateway account + , awaitEvent = config.awaitEvent + , activeBounce = + account + |> Account.getGateway + |> Maybe.andThen (flip Servers.get servers) + |> Maybe.andThen (flip Servers.getActiveBounce servers) + , onLogin = config.onJoinBank + , onLogout = config.onLeaveBank + , onSendSessionId = config.onSendBankSessionId + , onBankAccountUpdated = (\a b -> config.batchMsg []) -- Account.Msg <| DatabaseMsg Database. + , onHackedBankAccountUpdated = (\a b -> config.batchMsg []) + } + + metaConfig : Config msg -> Meta.Config msg metaConfig config = { toMsg = MetaMsg >> config.toMsg } diff --git a/src/Game/Messages.elm b/src/Game/Messages.elm index d6dcb687..6eb909a2 100644 --- a/src/Game/Messages.elm +++ b/src/Game/Messages.elm @@ -2,6 +2,7 @@ module Game.Messages exposing (..) import Json.Decode exposing (Value) import Game.Account.Messages as Account +import Game.Bank.Messages as Bank import Game.Servers.Messages as Servers import Game.Meta.Messages as Meta import Game.Storyline.Messages as Story @@ -14,6 +15,7 @@ import Requests.Types exposing (ResponseType) type Msg = AccountMsg Account.Msg | ServersMsg Servers.Msg + | BankMsg Bank.Msg | MetaMsg Meta.Msg | StoryMsg Story.Msg | InventoryMsg Inventory.Msg diff --git a/src/Game/Meta/Types/Network.elm b/src/Game/Meta/Types/Network.elm index 0aa7a54f..0c83a675 100644 --- a/src/Game/Meta/Types/Network.elm +++ b/src/Game/Meta/Types/Network.elm @@ -52,6 +52,11 @@ isFromInternet ( id, _ ) = id == "::" +onInternet : IP -> NIP +onInternet ip = + ( "::", ip ) + + filterInternet : List NIP -> List NIP filterInternet list = List.filter isFromInternet list diff --git a/src/Game/Meta/Types/Network/Site.elm b/src/Game/Meta/Types/Network/Site.elm index ad45e00b..6ff86820 100644 --- a/src/Game/Meta/Types/Network/Site.elm +++ b/src/Game/Meta/Types/Network/Site.elm @@ -1,5 +1,6 @@ module Game.Meta.Types.Network.Site exposing (..) +import Game.Account.Finances.Models exposing (AtmId) import Game.Meta.Types.Network exposing (NIP) import Game.Servers.Filesystem.Shared as Filesystem @@ -45,7 +46,7 @@ type alias WebserverContent = type alias BankContent = { title : String - , nip : NIP + , atmId : AtmId } diff --git a/src/Game/Models.elm b/src/Game/Models.elm index 68443774..2acb2e7d 100644 --- a/src/Game/Models.elm +++ b/src/Game/Models.elm @@ -4,6 +4,8 @@ module Game.Models , initialModel , getAccount , setAccount + , getBank + , setBank , getInventory , setInventory , getServers @@ -32,6 +34,7 @@ import Native.Panic import Core.Error as Error import Game.Account.Models as Account import Game.Account.Bounces.Models as Bounces +import Game.Bank.Models as Bank import Game.Servers.Models as Servers import Game.Inventory.Models as Inventory import Game.Servers.Shared as Servers @@ -45,6 +48,7 @@ import Core.Flags exposing (Flags) type alias Model = { account : Account.Model + , bank : Bank.Model , inventory : Inventory.Model , servers : Servers.Model , meta : Meta.Model @@ -67,6 +71,7 @@ initialModel : -> Model initialModel id username token flags = { account = Account.initialModel id username token + , bank = Bank.initialModel , inventory = Inventory.initialModel , servers = Servers.initialModel , meta = Meta.initialModel @@ -91,6 +96,16 @@ setAccount account model = { model | account = account } +getBank : Model -> Bank.Model +getBank = + .bank + + +setBank : Bank.Model -> Model -> Model +setBank bank model = + { model | bank = bank } + + getInventory : Model -> Inventory.Model getInventory = .inventory diff --git a/src/Game/Servers/Processes/Models.elm b/src/Game/Servers/Processes/Models.elm index a131d044..57977cca 100644 --- a/src/Game/Servers/Processes/Models.elm +++ b/src/Game/Servers/Processes/Models.elm @@ -5,6 +5,7 @@ import Time exposing (Time) import Random.Pcg as Random import Utils.Model.RandomUuid as RandomUuid import Game.Meta.Types.Network as Network +import Game.Account.Finances.Models exposing (AtmId, AccountId) import Game.Servers.Tunnels.Models exposing (ConnectionID) import Game.Servers.Logs.Models as Logs import Game.Servers.Processes.Shared exposing (..) @@ -43,6 +44,11 @@ type | Download DownloadContent | Upload UploadContent | VirusCollect + | BankAccountOpen BankAccountOpenContent + | BankAccountClose BankAccountCloseContent + | BankPasswordReveal BankPasswordRevealContent + | BankPasswordChange BankPasswordChangeContent + | BankTransfer BankTransferContent type alias EncryptorContent = @@ -50,6 +56,34 @@ type alias EncryptorContent = } +type alias BankAccountOpenContent = + { atmId : AtmId + } + + +type alias BankAccountCloseContent = + { accountId : AccountId + } + + +type alias BankPasswordChangeContent = + { accountId : AccountId + } + + +type alias BankTransferContent = + { fromAccount : AccountId + , toAccount : AccountId + , value : Int + } + + +type alias BankPasswordRevealContent = + { token : String + , accountId : AccountId + } + + type TransferType = PublicFTP | PrivateFTP @@ -453,6 +487,21 @@ getName process = VirusCollect -> "Virus Collect" + BankAccountOpen _ -> + "Bank Account Oppening" + + BankAccountClose _ -> + "Bank Account Closing" + + BankTransfer _ -> + "Bank Transference" + + BankPasswordReveal _ -> + "Bank Account Password Revealing" + + BankPasswordChange _ -> + "Bank Account Password Change" + getPercentUsage : Usage -> Float getPercentUsage = diff --git a/src/Game/Servers/Requests/Browse.elm b/src/Game/Servers/Requests/Browse.elm index 5737e4f2..2fc307af 100644 --- a/src/Game/Servers/Requests/Browse.elm +++ b/src/Game/Servers/Requests/Browse.elm @@ -171,7 +171,7 @@ bank : Decoder Site.Type bank = decode Site.BankContent |> required "title" string - |> required "nip" Decoders.Network.nipTuple + |> required "atm_id" string |> map Site.Bank |> content diff --git a/src/Game/Update.elm b/src/Game/Update.elm index 0836bf55..82939c1a 100644 --- a/src/Game/Update.elm +++ b/src/Game/Update.elm @@ -10,6 +10,9 @@ import Decoders.Game import Game.Account.Messages as Account import Game.Account.Models as Account import Game.Account.Update as Account +import Game.Bank.Messages as Bank +import Game.Bank.Models as Bank +import Game.Bank.Update as Bank import Game.Meta.Messages as Meta import Game.Meta.Update as Meta import Game.Meta.Models as Meta @@ -46,6 +49,9 @@ update config msg model = AccountMsg msg -> onAccount config msg model + BankMsg msg -> + onBank config msg model + ServersMsg msg -> onServers config msg model @@ -117,6 +123,21 @@ onAccount config msg model = ( model_, react ) +onBank : Config msg -> Bank.Msg -> Model -> UpdateResponse msg +onBank config msg model = + let + config_ = + bankConfig (getAccount model) (getServers model) (getFlags model) config + + ( bank, react ) = + Bank.update config_ msg <| getBank model + + model_ = + { model | bank = bank } + in + ( model_, react ) + + onMeta : Config msg -> Meta.Msg -> Model -> UpdateResponse msg onMeta config msg model = let diff --git a/src/OS/WindowManager/Config.elm b/src/OS/WindowManager/Config.elm index 90ebac37..6a7dc814 100644 --- a/src/OS/WindowManager/Config.elm +++ b/src/OS/WindowManager/Config.elm @@ -38,6 +38,8 @@ import Game.Account.Database.Models as Database import Game.Account.Finances.Messages as Finances import Game.Account.Notifications.Shared as AccountNotifications import Game.Account.Requests.ActionPerformed as ActionPerformed +import Game.Bank.Models as Bank +import Game.Bank.Messages as Bank import Game.Meta.Models as Meta import Game.Meta.Types.Desktop.Apps as DesktopApp exposing (DesktopApp) import Game.Meta.Types.Context exposing (Context(..)) @@ -173,10 +175,31 @@ browserConfig appId activeServer ( gCId, gServer ) config = Processes.HandleStartBruteforce >> processes config gCId onBankAccountLogin = - Finances.HandleBankAccountLogin >>> finances config + Bank.HandleLogin >>>> bank config + + onBankAccountLoginToken = + Bank.HandleLoginToken >>>> bank config onBankAccountTransfer = - Finances.HandleBankAccountTransfer >>> finances config + Bank.HandleTransfer >>>>>> bank config + + onBankAccountCreate = + Bank.HandleCreateAccount >>> bank config + + onBankAccountClose = + Bank.HandleCloseAccount >>> bank config + + onBankAccountChangePass = + Bank.HandleChangePassword >>> bank config + + onBankRevealPassword = + Bank.HandleRevealPassword >>>> bank config + + onBankResync = + Bank.HandleResync >>> bank config + + onBankAccountLogout = + Bank.HandleLogout >>> bank config in { flags = config.flags , toMsg = BrowserMsg >> AppMsg appId >> config.toMsg @@ -189,6 +212,9 @@ browserConfig appId activeServer ( gCId, gServer ) config = |> accountFromConfig |> Account.getDatabase |> Database.getHackedServers + , bank = + config + |> bankFromConfig , onNewApp = NewApp >>>>> config.toMsg , onOpenApp = OpenApp >>> config.toMsg , onSetContext = Account.HandleSetContext >> account config @@ -198,6 +224,12 @@ browserConfig appId activeServer ( gCId, gServer ) config = , onNewPublicDownload = onNewPublicDownload , onNewBruteforceProcess = onNewBruteforceProcess , onBankAccountLogin = onBankAccountLogin + , onBankAccountLoginToken = onBankAccountLoginToken + , onBankAccountChangePass = onBankAccountChangePass + , onBankAccountCreate = onBankAccountCreate + , onBankAccountClose = onBankAccountClose + , onBankAccountLogout = onBankAccountLogout + , onBankResync = onBankResync , onBankAccountTransfer = onBankAccountTransfer , menuAttr = config.menuAttr } @@ -417,6 +449,11 @@ account config = Game.AccountMsg >> config.gameMsg +bank : Config msg -> Bank.Msg -> msg +bank config = + Game.BankMsg >> config.gameMsg + + bounces : Config msg -> Bounces.Msg -> msg bounces config = Account.BouncesMsg >> account config @@ -514,6 +551,11 @@ accountFromConfig { game } = Game.getAccount game +bankFromConfig : Config msg -> Bank.Model +bankFromConfig { game } = + Game.getBank game + + storyFromConfig : Config msg -> Storyline.Model storyFromConfig { game } = Game.getStory game diff --git a/src/Requests/Topics.elm b/src/Requests/Topics.elm index 30a2cb87..3f6a0682 100644 --- a/src/Requests/Topics.elm +++ b/src/Requests/Topics.elm @@ -2,6 +2,7 @@ module Requests.Topics exposing (..) import Driver.Websocket.Channels exposing (..) import Game.Account.Models as Account +import Game.Account.Finances.Models as Finances import Game.Servers.Shared as Servers @@ -54,6 +55,45 @@ accountConfigSet id = WebsocketTopic (AccountChannel id) "config.set" +accountBankCreateAcc : Account.ID -> Topic +accountBankCreateAcc id = + WebsocketTopic (AccountChannel id) "bank.createacc" + + + +-- bank + + +bankResync : Finances.AccountId -> String -> Topic +bankResync bankAccId requestId = + WebsocketTopic (BankChannel bankAccId requestId) "bootstrap" + + +bankTransfer : Finances.AccountId -> String -> Topic +bankTransfer bankAccId requestId = + WebsocketTopic (BankChannel bankAccId requestId) "bank.transfer" + + +bankChangePass : Finances.AccountId -> String -> Topic +bankChangePass bankAccId requestId = + WebsocketTopic (BankChannel bankAccId requestId) "bank.changepass" + + +bankCloseAcc : Finances.AccountId -> String -> Topic +bankCloseAcc bankAccId requestId = + WebsocketTopic (BankChannel bankAccId requestId) "bank.closeacc" + + +bankLogout : Finances.AccountId -> String -> Topic +bankLogout bankAccId requestId = + WebsocketTopic (BankChannel bankAccId requestId) "bank.logout" + + +bankRevealPass : Servers.CId -> Topic +bankRevealPass cid = + WebsocketTopic (ServerChannel cid) "bank.reveal" + + -- server @@ -194,16 +234,6 @@ emailReply id = WebsocketTopic (AccountChannel id) "email.reply" -bankLogin : Account.ID -> Topic -bankLogin id = - WebsocketTopic (AccountChannel id) "bank.login" - - -bankTransfer : Account.ID -> Topic -bankTransfer id = - WebsocketTopic (AccountChannel id) "bank.transfer" - - bounceCreate : Account.ID -> Topic bounceCreate id = WebsocketTopic (AccountChannel id) "bounce.create" diff --git a/src/Utils/Maybe.elm b/src/Utils/Maybe.elm index ea78da19..7b4e7e8c 100644 --- a/src/Utils/Maybe.elm +++ b/src/Utils/Maybe.elm @@ -1,5 +1,7 @@ module Utils.Maybe exposing (..) +import Utils.React as React exposing (React) + uncurry : Maybe a -> Maybe b -> Maybe ( a, b ) uncurry ma mb = @@ -29,3 +31,23 @@ isNothing m = Just _ -> False + + +react : (a -> React b) -> Maybe a -> c -> ( c, React b ) +react r m i = + case m of + Nothing -> + React.update i + + Just j -> + ( i, r j ) + + +react2 : (a -> c -> React b) -> Maybe a -> Maybe c -> d -> ( d, React b ) +react2 r m1 m2 i = + case uncurry m1 m2 of + Just ( a, b ) -> + ( i, r a b ) + + Nothing -> + React.update i diff --git a/src/Utils/React.elm b/src/Utils/React.elm index 39b547cf..1e9c53a9 100644 --- a/src/Utils/React.elm +++ b/src/Utils/React.elm @@ -8,12 +8,14 @@ module Utils.React , addCmd , batch , map + , maybeUpdate , update , toCmd , split ) import Task +import Utils.Core exposing (..) type React msg @@ -153,3 +155,8 @@ merge func react1 react2 = toCmd_ : msg -> Cmd msg toCmd_ msg = Task.perform (always msg) (Task.succeed ()) + + +maybeUpdate : (a -> React b) -> Maybe a -> model -> ( model, React b ) +maybeUpdate = + Maybe.map >>> Maybe.withDefault none >>> flip (,)