diff --git a/dApp/user/src/Apollo.bs.js b/dApp/user/src/Apollo.bs.js index 0dabb4c..0415428 100644 --- a/dApp/user/src/Apollo.bs.js +++ b/dApp/user/src/Apollo.bs.js @@ -2,7 +2,7 @@ import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; import * as ApolloClient from "rescript-apollo-client/src/ApolloClient.bs.js"; -import * as Ethers$FlowsUserApp from "./lib/Ethers/Ethers.bs.js"; +import * as Auth$FlowsUserApp from "./lib/Auth/Auth.bs.js"; import * as ApolloClient__Link_Ws from "rescript-apollo-client/src/@apollo/client/link/ws/ApolloClient__Link_Ws.bs.js"; import * as ApolloClient__Utilities from "rescript-apollo-client/src/@apollo/client/utilities/ApolloClient__Utilities.bs.js"; import * as ApolloClient__ApolloClient from "rescript-apollo-client/src/@apollo/client/ApolloClient__ApolloClient.bs.js"; @@ -17,30 +17,12 @@ var headers = { "x-hasura-admin-secret": "testing" }; -function getAuthHeaders(user) { - if (user === undefined) { - return ; - } - var u = Caml_option.valFromOption(user); - var getUserSignature = function (__x) { - return Caml_option.null_to_opt(__x.getItem(Ethers$FlowsUserApp.Utils.ethAdrToLowerStr(u))); - }; - var uS = getUserSignature(localStorage); - if (uS !== undefined) { - return { - "eth-address": Ethers$FlowsUserApp.Utils.ethAdrToStr(u), - "eth-signature": uS - }; - } - -} - var httpLink = ApolloClient__Link_Http_HttpLink.make((function (param) { return "http://localhost:8080/v1/graphql"; }), undefined, undefined, Caml_option.some(headers), undefined, undefined, undefined, undefined); function makeHttpLink(user) { - var headers = getAuthHeaders(user); + var headers = Auth$FlowsUserApp.$$Headers.makeFromOpt(user); return ApolloClient__Link_Http_HttpLink.make((function (param) { return "http://localhost:8080/v1/graphql"; }), undefined, undefined, Caml_option.some(headers !== undefined ? headers : (function (prim) { @@ -73,7 +55,6 @@ function makeClient(user) { export { graphqlEndpoint , headers , - getAuthHeaders , httpLink , makeHttpLink , wsLink , diff --git a/dApp/user/src/Apollo.res b/dApp/user/src/Apollo.res index afe0b96..74b4cfe 100644 --- a/dApp/user/src/Apollo.res +++ b/dApp/user/src/Apollo.res @@ -3,26 +3,6 @@ let graphqlEndpoint = "localhost:8080/v1/graphql" let headers = {"x-hasura-admin-secret": "testing"} -type clientHeaders = { - @as("eth-address") - ethAddress: string, - @as("eth-signature") - ethSignature: string, -} - -let getAuthHeaders = (~user) => { - open Ethers.Utils - switch(user){ - | None => None - | Some(u) => { - let getUserSignature = Dom.Storage2.getItem(_, u->ethAdrToLowerStr) - switch(getUserSignature(Dom.Storage2.localStorage)){ - | None => None - | Some(uS) => Some({ethAddress: u->ethAdrToStr, ethSignature: uS}) - } - } - } -} let httpLink = ApolloClient.Link.HttpLink.make( ~uri=_ => "http://" ++ graphqlEndpoint, @@ -33,7 +13,7 @@ let httpLink = ApolloClient.Link.HttpLink.make( let makeHttpLink = (~user) => ApolloClient.Link.HttpLink.make( ~uri= _ => "http://" ++ graphqlEndpoint, ~headers={ - switch(getAuthHeaders(~user)){ + switch(Auth.Headers.makeFromOpt(~optUser=user)){ | Some(headers) => headers->Obj.magic | None => Js.Obj.empty->Obj.magic } diff --git a/dApp/user/src/App.bs.js b/dApp/user/src/App.bs.js index f97b34d..855cbeb 100644 --- a/dApp/user/src/App.bs.js +++ b/dApp/user/src/App.bs.js @@ -1,6 +1,8 @@ // Generated by ReScript, PLEASE EDIT WITH CARE import * as React from "react"; +import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; +import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; import * as Client from "@apollo/client"; import * as Dapp$FlowsUserApp from "./Dapp.bs.js"; import * as Login$FlowsUserApp from "./Login/Login.bs.js"; @@ -26,9 +28,10 @@ var OnlyLoggedIn = { }; function App$Main(Props) { - return React.createElement(App$OnlyLoggedIn, { - children: null - }, React.createElement("h1", undefined, "Main component"), React.createElement(Dapp$FlowsUserApp.make, {})); + var match = AuthProvider$FlowsUserApp.useAuthStatus(undefined); + return React.createElement(React.Fragment, undefined, React.createElement("h3", undefined, "Auth Status"), React.createElement("div", undefined, AuthProvider$FlowsUserApp.loggedInStatusToStr(match.loggedInStatus)), React.createElement(App$OnlyLoggedIn, { + children: null + }, React.createElement("h1", undefined, "Main component"), React.createElement(Dapp$FlowsUserApp.make, {}))); } var Main = { @@ -62,10 +65,16 @@ var Router = { function App$GraphQl(Props) { var children = Props.children; - var user = RootProvider$FlowsUserApp.useCurrentUser(undefined); + var optWeb3User = RootProvider$FlowsUserApp.useCurrentUser(undefined); + var match = AuthProvider$FlowsUserApp.useAuthStatus(undefined); + var loggedInStatus = match.loggedInStatus; + var optDbOnlyUser = typeof loggedInStatus === "number" ? undefined : Caml_option.some(loggedInStatus._0); + var optUser = Belt_Option.isSome(optWeb3User) ? optWeb3User : ( + Belt_Option.isSome(optDbOnlyUser) ? optDbOnlyUser : undefined + ); var client = React.useMemo((function () { - return Apollo$FlowsUserApp.makeClient(user); - }), [user]); + return Apollo$FlowsUserApp.makeClient(optUser); + }), [optUser]); return React.createElement(Client.ApolloProvider, { client: client, children: children @@ -78,8 +87,8 @@ var GraphQl = { function App(Props) { return React.createElement(RootProvider$FlowsUserApp.make, { - children: React.createElement(App$GraphQl, { - children: React.createElement(AuthProvider$FlowsUserApp.make, { + children: React.createElement(AuthProvider$FlowsUserApp.make, { + children: React.createElement(App$GraphQl, { children: React.createElement(App$Router, {}) }) }) diff --git a/dApp/user/src/App.res b/dApp/user/src/App.res index 175c3b2..e98a5a4 100644 --- a/dApp/user/src/App.res +++ b/dApp/user/src/App.res @@ -12,7 +12,20 @@ module OnlyLoggedIn = { module Main = { @react.component let make = () => { -

{"Main component"->React.string}

+ open AuthProvider + let { loggedInStatus } = useAuthStatus() + <> +

+ {"Auth Status" -> React.string} +

+
+ { loggedInStatus->loggedInStatusToStr->React.string } +
+ +

{"Main component"->React.string}

+ +
+ } } module NotFound = { @@ -38,12 +51,27 @@ module Router = { module GraphQl = { @react.component let make = (~children) => { - let user = RootProvider.useCurrentUser() + let optWeb3User = RootProvider.useCurrentUser() + let { loggedInStatus } = AuthProvider.useAuthStatus() + let optDbOnlyUser = switch(loggedInStatus){ + | DbOnly(user) => Some(user) + | _ => None + } + + let optUser = if(Option.isSome(optWeb3User)){ + optWeb3User + }else if(Option.isSome(optDbOnlyUser)){ + optDbOnlyUser + } else{ + None + } + + let client = React.useMemo1(() => Apollo.makeClient( - ~user + ~user=optUser ) - , [user]) + , [optUser]) children } @@ -51,9 +79,9 @@ module GraphQl = { @react.component let make = () => - - + + + - - \ No newline at end of file + diff --git a/dApp/user/src/Dapp.bs.js b/dApp/user/src/Dapp.bs.js index b78cd94..c5edfb4 100644 --- a/dApp/user/src/Dapp.bs.js +++ b/dApp/user/src/Dapp.bs.js @@ -12,6 +12,7 @@ function Dapp(Props) { var optWeb3Provider = RootProvider$FlowsUserApp.useWeb3(undefined); var optSigner = RootProvider$FlowsUserApp.useSigner(undefined); var match = AuthProvider$FlowsUserApp.useAuthStatus(undefined); + var loggedInStatus = match.loggedInStatus; React.useEffect((function () { if (optWeb3Provider !== undefined && optSigner !== undefined) { RaidenTs.Raiden.create(Caml_option.valFromOption(optWeb3Provider), 0); @@ -21,7 +22,24 @@ function Dapp(Props) { optWeb3Provider, optSigner ]); - return React.createElement("div", undefined, match.isAuthorized ? React.createElement(SignUp$FlowsUserApp.make, {}) : React.createElement(AuthenticateButton$FlowsUserApp.make, {}), React.createElement("p", undefined, "something")); + var tmp; + if (typeof loggedInStatus === "number") { + switch (loggedInStatus) { + case /* Web3AndDb */0 : + tmp = React.createElement(SignUp$FlowsUserApp.make, {}); + break; + case /* Web3Only */1 : + tmp = React.createElement(AuthenticateButton$FlowsUserApp.make, {}); + break; + case /* NotLoggedIn */2 : + tmp = null; + break; + + } + } else { + tmp = React.createElement(SignUp$FlowsUserApp.make, {}); + } + return React.createElement("div", undefined, tmp, React.createElement("p", undefined, "something")); } var make = Dapp; diff --git a/dApp/user/src/Dapp.res b/dApp/user/src/Dapp.res index f62a154..057e657 100644 --- a/dApp/user/src/Dapp.res +++ b/dApp/user/src/Dapp.res @@ -3,7 +3,7 @@ let make = () => { let optWeb3Provider = RootProvider.useWeb3() let optSigner = RootProvider.useSigner() - let { isAuthorized } = AuthProvider.useAuthStatus() + let { loggedInStatus } = AuthProvider.useAuthStatus() React.useEffect2(() => { switch (optWeb3Provider, optSigner) { @@ -16,10 +16,10 @@ let make = () => { }, (optWeb3Provider, optSigner))
{ - if(!isAuthorized){ - - }else{ - + switch(loggedInStatus){ + | Web3Only => + | NotLoggedIn => React.null + | _ => } }

diff --git a/dApp/user/src/components/Auth/AuthenticateButton.bs.js b/dApp/user/src/components/Auth/AuthenticateButton.bs.js index 03982a6..bc02bcd 100644 --- a/dApp/user/src/components/Auth/AuthenticateButton.bs.js +++ b/dApp/user/src/components/Auth/AuthenticateButton.bs.js @@ -2,6 +2,7 @@ import * as Curry from "bs-platform/lib/es6/curry.js"; import * as React from "react"; +import * as Auth$FlowsUserApp from "../../lib/Auth/Auth.bs.js"; import * as Ethers$FlowsUserApp from "../../lib/Ethers/Ethers.bs.js"; import * as AuthProvider$FlowsUserApp from "../../lib/Auth/AuthProvider.bs.js"; import * as RootProvider$FlowsUserApp from "../../lib/Old/RootProvider.bs.js"; @@ -15,13 +16,14 @@ function AuthenticateButton(Props) { var signer = RootProvider$FlowsUserApp.useSignerExn(undefined); var userAddress = RootProvider$FlowsUserApp.useCurrentUserExn(undefined); var match = AuthProvider$FlowsUserApp.useAuthStatus(undefined); - var setIsAuthorized = match.setIsAuthorized; + var setLoggedInStatus = match.setLoggedInStatus; return React.createElement("button", { onClick: (function (param) { signer.signMessage("flows.finance-signin-string:" + Ethers$FlowsUserApp.Utils.ethAdrToStr(userAddress)).then(function (result) { - setSignInData(Ethers$FlowsUserApp.Utils.ethAdrToLowerStr(userAddress), String(result)); - return Curry._1(setIsAuthorized, (function (param) { - return true; + Auth$FlowsUserApp.LocalStorage.setSignInData(userAddress, String(result)); + Auth$FlowsUserApp.LocalStorage.setCurrentUser(userAddress); + return Curry._1(setLoggedInStatus, (function (param) { + return /* Web3AndDb */0; })); }); diff --git a/dApp/user/src/components/Auth/AuthenticateButton.res b/dApp/user/src/components/Auth/AuthenticateButton.res index 73b6fa0..54428cd 100644 --- a/dApp/user/src/components/Auth/AuthenticateButton.res +++ b/dApp/user/src/components/Auth/AuthenticateButton.res @@ -6,18 +6,21 @@ let setSignInData = (~ethAddress: string, ~ethSignature: string) => Dom.Storage2 let make = () => { let signer = RootProvider.useSignerExn() let userAddress = RootProvider.useCurrentUserExn() - let { setIsAuthorized } = AuthProvider.useAuthStatus() + let { setLoggedInStatus } = AuthProvider.useAuthStatus() -} \ No newline at end of file +} diff --git a/dApp/user/src/lib/Auth/Auth.bs.js b/dApp/user/src/lib/Auth/Auth.bs.js new file mode 100644 index 0000000..ee8227b --- /dev/null +++ b/dApp/user/src/lib/Auth/Auth.bs.js @@ -0,0 +1,66 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; +import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; +import * as Ethers$FlowsUserApp from "../Ethers/Ethers.bs.js"; + +var currentLoginKey = "CurrentUserLoggedIn"; + +function get(item) { + var __x = localStorage; + return Caml_option.null_to_opt(__x.getItem(item)); +} + +function set(key, item) { + localStorage.setItem(key, item); + +} + +function setSignInData(ethAddress, ethSignature) { + return set(Ethers$FlowsUserApp.Utils.ethAdrToLowerStr(ethAddress), ethSignature); +} + +function setCurrentUser(ethAddress) { + return set(currentLoginKey, Ethers$FlowsUserApp.Utils.ethAdrToLowerStr(ethAddress)); +} + +var getUserSignatureOpt = get; + +function getCurrentLoggedInUserOpt(param) { + return Belt_Option.flatMap(get(currentLoginKey), Ethers$FlowsUserApp.Utils.getAddress); +} + +var LocalStorage = { + currentLoginKey: currentLoginKey, + get: get, + set: set, + setSignInData: setSignInData, + setCurrentUser: setCurrentUser, + getUserSignatureOpt: getUserSignatureOpt, + getCurrentLoggedInUserOpt: getCurrentLoggedInUserOpt +}; + +function make(user) { + return Belt_Option.flatMap(get(Ethers$FlowsUserApp.Utils.ethAdrToLowerStr(user)), (function (ethSignature) { + return { + "eth-address": Ethers$FlowsUserApp.Utils.ethAdrToStr(user), + "eth-signature": ethSignature + }; + })); +} + +function makeFromOpt(optUser) { + return Belt_Option.flatMap(optUser, make); +} + +var $$Headers = { + make: make, + makeFromOpt: makeFromOpt +}; + +export { + LocalStorage , + $$Headers , + +} +/* Ethers-FlowsUserApp Not a pure module */ diff --git a/dApp/user/src/lib/Auth/Auth.res b/dApp/user/src/lib/Auth/Auth.res new file mode 100644 index 0000000..b8fe6ba --- /dev/null +++ b/dApp/user/src/lib/Auth/Auth.res @@ -0,0 +1,57 @@ +open Ethers +open Utils + +module LocalStorage = { + + + let currentLoginKey = "CurrentUserLoggedIn" + + + let get = (item) => { + let fn = Dom.Storage2.getItem(_, item) + fn(Dom.Storage2.localStorage) + } + + let set = (key, item) => { + Dom.Storage2.localStorage->Dom.Storage2.setItem(key, item) + } + + let setSignInData = + (~ethAddress, ~ethSignature: string) => + set(ethAddress->ethAdrToLowerStr, ethSignature) + + let setCurrentUser = + (~ethAddress: ethAddress) => + set(currentLoginKey, ethAddress->ethAdrToLowerStr) + + let getUserSignatureOpt = u => u->get + + let getCurrentLoggedInUserOpt = () => + get(currentLoginKey) + ->Option.flatMap(Ethers.Utils.getAddress) +} + +module Headers = { + + type clientHeaders = { + @as("eth-address") + ethAddress: string, + @as("eth-signature") + ethSignature: string, + } + + let make = (~user) => { + LocalStorage.getUserSignatureOpt(user->ethAdrToLowerStr) + ->Option.flatMap(ethSignature => + Some({ + ethAddress: user->ethAdrToStr, + ethSignature + }) + ) + } + + let makeFromOpt = + (~optUser: option) => + optUser->Option.flatMap((user) => make(~user)) + +} diff --git a/dApp/user/src/lib/Auth/AuthProvider.bs.js b/dApp/user/src/lib/Auth/AuthProvider.bs.js index 418327e..9a4c76e 100644 --- a/dApp/user/src/lib/Auth/AuthProvider.bs.js +++ b/dApp/user/src/lib/Auth/AuthProvider.bs.js @@ -3,12 +3,28 @@ import * as Curry from "bs-platform/lib/es6/curry.js"; import * as React from "react"; import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; -import * as Apollo$FlowsUserApp from "../../Apollo.bs.js"; +import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; +import * as Auth$FlowsUserApp from "./Auth.bs.js"; import * as RootProvider$FlowsUserApp from "../Old/RootProvider.bs.js"; +function loggedInStatusToStr(status) { + if (typeof status !== "number") { + return "DbOnly"; + } + switch (status) { + case /* Web3AndDb */0 : + return "Web3AndDb"; + case /* Web3Only */1 : + return "Web3Only"; + case /* NotLoggedIn */2 : + return "NotLoggedIn"; + + } +} + var context = React.createContext({ - isAuthorized: false, - setIsAuthorized: (function (param) { + loggedInStatus: /* NotLoggedIn */2, + setLoggedInStatus: (function (param) { }) }); @@ -34,27 +50,51 @@ var AuthContext = { Provider: Provider }; -function getUserAuthStatus(user) { - return Belt_Option.isSome(Apollo$FlowsUserApp.getAuthHeaders(user)); +function getDBAuthStatus(user) { + return Belt_Option.isSome(Auth$FlowsUserApp.$$Headers.make(user)); } function AuthProvider(Props) { var children = Props.children; var user = RootProvider$FlowsUserApp.useCurrentUser(undefined); var match = React.useState(function () { - return false; + return /* NotLoggedIn */2; }); - var setIsAuthorized = match[1]; + var setLoggedInStatus = match[1]; React.useEffect((function () { - Curry._1(setIsAuthorized, (function (param) { - return Belt_Option.isSome(Apollo$FlowsUserApp.getAuthHeaders(user)); - })); + if (user !== undefined) { + var user$1 = Caml_option.valFromOption(user); + Auth$FlowsUserApp.LocalStorage.setCurrentUser(user$1); + if (Belt_Option.isSome(Auth$FlowsUserApp.$$Headers.make(user$1))) { + Curry._1(setLoggedInStatus, (function (param) { + return /* Web3AndDb */0; + })); + } else { + Curry._1(setLoggedInStatus, (function (param) { + return /* Web3Only */1; + })); + } + } else { + var userOpt = Auth$FlowsUserApp.LocalStorage.getCurrentLoggedInUserOpt(undefined); + if (userOpt !== undefined) { + var user$2 = Caml_option.valFromOption(userOpt); + Curry._1(setLoggedInStatus, (function (param) { + return /* DbOnly */{ + _0: user$2 + }; + })); + } else { + Curry._1(setLoggedInStatus, (function (param) { + return /* NotLoggedIn */2; + })); + } + } }), [user]); return React.createElement(AuthProvider$AuthContext$Provider, { value: { - isAuthorized: match[0], - setIsAuthorized: setIsAuthorized + loggedInStatus: match[0], + setLoggedInStatus: setLoggedInStatus }, children: children }); @@ -67,8 +107,9 @@ function useAuthStatus(param) { var make = AuthProvider; export { + loggedInStatusToStr , AuthContext , - getUserAuthStatus , + getDBAuthStatus , make , useAuthStatus , diff --git a/dApp/user/src/lib/Auth/AuthProvider.res b/dApp/user/src/lib/Auth/AuthProvider.res index 72f84df..4f62d02 100644 --- a/dApp/user/src/lib/Auth/AuthProvider.res +++ b/dApp/user/src/lib/Auth/AuthProvider.res @@ -1,10 +1,21 @@ +type loggedInStatus = | Web3AndDb | Web3Only | @as("DbOnly") DbOnly(Ethers.ethAddress) | NotLoggedIn + +let loggedInStatusToStr = (status) => switch(status){ + | Web3AndDb=>"Web3AndDb" + | Web3Only=>"Web3Only" + | DbOnly(_)=>"DbOnly" + | NotLoggedIn=>"NotLoggedIn" +} + + type authContextType = { - isAuthorized: bool, - setIsAuthorized: ((bool => bool) => unit) + loggedInStatus: loggedInStatus, + setLoggedInStatus: ((loggedInStatus => loggedInStatus) => unit) } + module AuthContext = { - let context = React.createContext({isAuthorized: false, setIsAuthorized: (_)=> () }) + let context = React.createContext({loggedInStatus: NotLoggedIn, setLoggedInStatus: (_)=> () }) module Provider = { let provider = React.Context.provider(context) @@ -16,26 +27,45 @@ module AuthContext = { } } -let getUserAuthStatus = (user) => Apollo.getAuthHeaders(~user)->Option.isSome +let getDBAuthStatus = + user => + Auth.Headers.make(~user)->Option.isSome + @react.component let make = (~children) => { let user = RootProvider.useCurrentUser() - let (isAuthorized, setIsAuthorized) = React.useState(_ => false) + let (loggedInStatus, setLoggedInStatus) = React.useState(_ => NotLoggedIn) React.useEffect1(() => { - let _ = setIsAuthorized(_ => user->getUserAuthStatus) + switch(user){ + | Some(user) => { + Auth.LocalStorage.setCurrentUser(~ethAddress=user) + if(user->getDBAuthStatus){ + setLoggedInStatus(_ => Web3AndDb) + }else{ + setLoggedInStatus(_ => Web3Only) + } + } + | None => { + let userOpt = Auth.LocalStorage.getCurrentLoggedInUserOpt() + switch(userOpt){ + | Some(user) => setLoggedInStatus(_ => DbOnly(user)) + | None => setLoggedInStatus(_ => NotLoggedIn) + } + } + } None }, [user]) {children} } -let useAuthStatus = () => React.useContext(AuthContext.context) \ No newline at end of file +let useAuthStatus = () => React.useContext(AuthContext.context)