From 804865d94c12426e2f23b83aa8cfaee063a04398 Mon Sep 17 00:00:00 2001
From: RudeWolfCoding <51991885+RudeWolfCoding@users.noreply.github.com>
Date: Sun, 24 Oct 2021 08:45:10 +0200
Subject: [PATCH 1/5] Modal UI Fixes
Fixing the account selection and switches
---
dapp/src/actions/owner.js | 5 +++
.../common/ProfileDropDown/index.jsx | 35 ++++++++++++++-----
.../common/modals/LoginModal/index.jsx | 1 -
.../modals/SwitchAccountModal/index.js | 23 ++++++++++++
.../dashboard/pages/Plugins/index.jsx | 28 +++++++++++++--
dapp/src/constants/uiConstants.js | 1 +
dapp/src/containers/ModalContainer.jsx | 7 ++--
dapp/src/reducers/owner.js | 17 +++++++++
dapp/src/sagas/owner.js | 18 ++++++++++
9 files changed, 121 insertions(+), 14 deletions(-)
create mode 100644 dapp/src/actions/owner.js
create mode 100644 dapp/src/components/dashboard/modals/SwitchAccountModal/index.js
create mode 100644 dapp/src/reducers/owner.js
create mode 100644 dapp/src/sagas/owner.js
diff --git a/dapp/src/actions/owner.js b/dapp/src/actions/owner.js
new file mode 100644
index 000000000..6100310d9
--- /dev/null
+++ b/dapp/src/actions/owner.js
@@ -0,0 +1,5 @@
+import { createRequestTypes, requestAction } from './utils'
+
+export const OWNERSHIP = createRequestTypes('OWNERSHIP')
+export const isOwner = (accountAddress, communityAddress) => requestAction(OWNERSHIP, { accountAddress, communityAddress })
+export const setDefault = () => requestAction('DEFAULT')
\ No newline at end of file
diff --git a/dapp/src/components/common/ProfileDropDown/index.jsx b/dapp/src/components/common/ProfileDropDown/index.jsx
index c9ec94d69..9641f98b8 100644
--- a/dapp/src/components/common/ProfileDropDown/index.jsx
+++ b/dapp/src/components/common/ProfileDropDown/index.jsx
@@ -52,7 +52,7 @@ const ProfileDropDown = ({
}
} else {
const desired = networkType === 'ropsten' ? 'main' : 'ropsten'
- loadSwitchModal(desired)
+ loadSwitchModal('fuse')
}
} else if (providerInfo.type === 'web') {
if (foreignNetwork) {
@@ -94,16 +94,33 @@ const ProfileDropDown = ({
- Connected to {providerInfo.check && providerInfo.check.substring && providerInfo.check.substring(2)}
- (Disconnect)
+ Connected to
+ {providerInfo.check &&
+ providerInfo.check.substring &&
+ providerInfo.check.substring(2)}
+
+
+
+ Disconnect
+
-
-
-
- Switch to {capitalize(convertNetworkName((foreignNetwork === networkType ? 'fuse' : foreignNetwork) || (networkType === 'ropsten' ? 'main' : 'ropsten')))} network
-
-
+ {networkType === "fuse" ? ("") : (
+
+
+
+
+ Switch to{" "}
+ {capitalize(
+ convertNetworkName(
+ foreignNetwork === networkType ? "fuse" : "fuse"
+ )
+ )}{" "}
+ network
+
+
+
+ )}
)
diff --git a/dapp/src/components/common/modals/LoginModal/index.jsx b/dapp/src/components/common/modals/LoginModal/index.jsx
index 609bab28f..8a3c81992 100644
--- a/dapp/src/components/common/modals/LoginModal/index.jsx
+++ b/dapp/src/components/common/modals/LoginModal/index.jsx
@@ -33,7 +33,6 @@ export default ({ hideModal, handleConnect }) => {
render={renderButton}
onSuccess={handleLogin}
cookiePolicy='single_host_origin'
- isSignedIn
/>
)
diff --git a/dapp/src/components/dashboard/modals/SwitchAccountModal/index.js b/dapp/src/components/dashboard/modals/SwitchAccountModal/index.js
new file mode 100644
index 000000000..34563d550
--- /dev/null
+++ b/dapp/src/components/dashboard/modals/SwitchAccountModal/index.js
@@ -0,0 +1,23 @@
+
+import React from "react";
+import Modal from "components/common/Modal";
+
+const SwitchAccountsModal = ({ communityCreator, hideModal, hasCloseBtn = true }) => {
+
+
+
You are on wrong Metamask account
+
+ Can't perform an economy action! Please switch your Metamask account to: {communityCreator}
+
+
+
+ ;
+};
+
+export default SwitchAccountsModal;
\ No newline at end of file
diff --git a/dapp/src/components/dashboard/pages/Plugins/index.jsx b/dapp/src/components/dashboard/pages/Plugins/index.jsx
index 872e18c02..6694df75b 100644
--- a/dapp/src/components/dashboard/pages/Plugins/index.jsx
+++ b/dapp/src/components/dashboard/pages/Plugins/index.jsx
@@ -14,6 +14,8 @@ import FiatOnRamp from 'images/fiat-on-ramp.png'
import FiatOnRampBig from 'images/fiat-on-ramp-big.png'
import WalletBannerLink from 'images/wallet_banner_link.png'
import WalletBannerLinkBig from 'images/wallet_banner_link_big.png'
+import { useEffect } from 'react'
+import { setDefault, isOwner } from 'actions/owner'
const generalPlugins = ([
{
@@ -98,8 +100,13 @@ const PluginList = ({ pluginList, pluginTile, plugins, showInfoModal, addPlugin,
const Plugins = ({
loadModal,
addCommunityPlugin,
- community
+ community,
+ address,
+ isAdmin,
+ isOwner,
+ communityCreator
}) => {
+ const dispatch = useDispatch()
const { address: communityAddress } = useParams()
const { plugins } = community
const showInfoModal = (key, props) => {
@@ -140,6 +147,18 @@ const Plugins = ({
return plugin
}
+ useEffect(()=>{
+ dispatch(isOwner(communityAddress, address))
+ if(isOwner && !isAdmin){
+ loadModal(SWITCH_ACCOUNT_MODAL), {
+ ...props,
+ }
+ }
+ return () =>{
+ dispatch(setDefault)
+ }
+ }, [dispatch])
+
return (
community ?
Plugins
@@ -163,4 +182,9 @@ const mapDispatchToProps = {
addCommunityPlugin
}
-export default connect(null, mapDispatchToProps)(Plugins)
+const mapStateToProps = (state) => ({
+ address: getAccountAddress(state)
+
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(Plugins)
diff --git a/dapp/src/constants/uiConstants.js b/dapp/src/constants/uiConstants.js
index 2bcc57ec8..148055b4c 100644
--- a/dapp/src/constants/uiConstants.js
+++ b/dapp/src/constants/uiConstants.js
@@ -9,3 +9,4 @@ export const IMAGE_CROPPER_MODAL = 'IMAGE_CROPPER_MODAL'
export const PLUGIN_INFO_MODAL = 'PLUGIN_INFO_MODAL'
export const SWITCH_NETWORK = 'SWITCH_NETWORK'
export const LOGIN_MODAL = 'LOGIN_MODAL'
+export const SWITCH_ACCOUNT_MODAL = 'SWITCH_ACCOUNT_MODAL'
\ No newline at end of file
diff --git a/dapp/src/containers/ModalContainer.jsx b/dapp/src/containers/ModalContainer.jsx
index baf1e68a7..883f37afb 100644
--- a/dapp/src/containers/ModalContainer.jsx
+++ b/dapp/src/containers/ModalContainer.jsx
@@ -14,6 +14,7 @@ import ImportExistingEntity from 'components/dashboard/modals/ImportExistingEnti
import PluginInfoModal from 'components/dashboard/modals/PluginInfoModal'
import SwitchNetwork from 'components/common/SwitchNetwork'
import LoginModal from 'components/common/modals/LoginModal'
+import SwitchAccountModal from 'components/dashboard/modals/SwitchAccountModal'
import {
WRONG_NETWORK_MODAL,
@@ -26,7 +27,8 @@ import {
IMAGE_CROPPER_MODAL,
PLUGIN_INFO_MODAL,
SWITCH_NETWORK,
- LOGIN_MODAL
+ LOGIN_MODAL,
+ SWITCH_ACCOUNT_MODAL
} from 'constants/uiConstants'
const renderModal = (modalComponent, props) =>
@@ -45,7 +47,8 @@ const MODAL_COMPONENTS = {
[IMAGE_CROPPER_MODAL]: ImageCropperModal,
[PLUGIN_INFO_MODAL]: PluginInfoModal,
[SWITCH_NETWORK]: SwitchNetwork,
- [LOGIN_MODAL]: LoginModal
+ [LOGIN_MODAL]: LoginModal,
+ [SWITCH_ACCOUNT_MODAL]: SwitchAccountModal
}
const ModalContainer = (props) => {
diff --git a/dapp/src/reducers/owner.js b/dapp/src/reducers/owner.js
new file mode 100644
index 000000000..b67d13f77
--- /dev/null
+++ b/dapp/src/reducers/owner.js
@@ -0,0 +1,17 @@
+import * as owner from 'actions/owner'
+
+const initialState = {
+ isAdmin: false,
+ isOwner: false,
+ creatorAddress: undefined,
+}
+
+
+export default (state = initialState, action) => {
+ switch (action.type) {
+ case owner.DEFAULT:
+ return { ...state }
+ case owner.OWNERSHIP:
+ return { ...action.response }
+ }
+}
\ No newline at end of file
diff --git a/dapp/src/sagas/owner.js b/dapp/src/sagas/owner.js
new file mode 100644
index 000000000..5507b07e9
--- /dev/null
+++ b/dapp/src/sagas/owner.js
@@ -0,0 +1,18 @@
+import { all, put } from "redux-saga/effects";
+import { apiCall, tryTakeEvery } from "./utils";
+import { fetchOwner } from "services/api/entities";
+import * as actions from "actions/owner";
+
+function* isOwner({ accountAddress, communityAddress }) {
+ const response = yield apiCall(fetchOwner, { accountAddress, communityAddress });
+ yield put({
+ type: actions.OWNERSHIP.SUCCESS,
+ accountAddress,
+ communityAddress,
+ response,
+ });
+}
+
+export default function* ownerSaga() {
+ yield all([tryTakeEvery(actions.OWNERSHIP, isOwner, 1)]);
+}
\ No newline at end of file
From 2ff70a326173f77d501fbf1085a0eaba58c092e2 Mon Sep 17 00:00:00 2001
From: RudeWolfCoding <51991885+RudeWolfCoding@users.noreply.github.com>
Date: Sun, 24 Oct 2021 08:47:44 +0200
Subject: [PATCH 2/5] Backend Entity Ownership route
Adds route to the server to check if entity is the community owner/admin
---
server/src/routes/api/v1/entities.js | 47 ++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/server/src/routes/api/v1/entities.js b/server/src/routes/api/v1/entities.js
index 28f48849f..6806d9106 100644
--- a/server/src/routes/api/v1/entities.js
+++ b/server/src/routes/api/v1/entities.js
@@ -10,6 +10,9 @@ const Community = mongoose.model('Community')
const Token = mongoose.model('Token')
const { sortBy, keyBy, get, has, last } = require('lodash')
const { toChecksumAddress } = require('web3-utils')
+const UserAccount = mongoose.model('UserAccount')
+const auth = require('@routes/auth')
+const { ObjectId } = mongoose.Types
const withCommunities = async (entities) => {
const communityAddresses = entities.map(token => token.communityAddress)
@@ -206,4 +209,48 @@ router.get('/:communityAddress', async (req, res, next) => {
})
})
+/**
+ * @apiDefine Onwership Data
+ * @apiDescription Resolves whether FuseStudioUser Accounts is admin on different wallet address
+ * @apiSuccess {String} account Community account address of owner
+ * @apiSuccess {Boolean} isAdmin
+ */
+
+/**
+ * @api {get} /entities/owner/:communityAddress/:account Fetch entity
+ * @apiName GetEntity
+ * @apiGroup Entity
+ *
+ * @apiParam {String} communityAddress Community address
+ * @apiParam {String} emails user's registered email
+ *
+ * @apiUse EntityData
+ */
+ router.post('/owner/:communityAddress/:account', auth.required, async (req, res, next) => {
+ const { account, communityAddress } = req.params
+ const { id } = req.user
+ const userAccounts = await UserAccount.find({ studioUser: ObjectId(id) })
+ const result = {isAdmin: false, isOwner: false, creatorAddress: undefined}
+ userAccounts.forEach(async (user) => {
+ const entities = await Entity.find(ObjectId(user.accountAddress)).sort({ blockNumber: -1 })
+ const data = await withCommunities(entities)
+ const communitiesUserOwn = sortBy(data.filter(({ isAdmin }) => isAdmin), ['updatedAt']).reverse()
+ communitiesUserOwn.forEach((communityOwned) =>{
+ if (communityOwned.community.communityAddress === communityAddress){
+ result.isOwner = true
+ result.creatorAddress = communitiesUserOwn.creatorAddress
+ if(communityOwned.comunity.creatorAddress === account ){
+ result.isAdmin = true;
+ }
+ return result
+ }
+ })
+ });
+
+ /* if user is on valid account return isAdmin: true, isOwner: true, accountAddress: account
+ if user has valid account return isAdmin: false, isOwner: true, accountAddress: accountAddress
+ if user is not owner return isAdmin: false, isOwner: false, accountAddress: undefined */
+ return res.json(result)
+})
+
module.exports = router
From 891fa774ce868daa34a994507064d79927fb16ea Mon Sep 17 00:00:00 2001
From: RudeWolfCoding <51991885+RudeWolfCoding@users.noreply.github.com>
Date: Sun, 24 Oct 2021 11:29:01 +0200
Subject: [PATCH 3/5] HomePage Bugfixes
Small bug-fixes
---
dapp/assets/images/fuse_logo_white.svg | 42 ++++++++++++++-----
dapp/src/components/common/NavBar/index.jsx | 2 +-
.../components/home/components/Faq/index.jsx | 2 +-
3 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/dapp/assets/images/fuse_logo_white.svg b/dapp/assets/images/fuse_logo_white.svg
index 284922c8a..472e30661 100644
--- a/dapp/assets/images/fuse_logo_white.svg
+++ b/dapp/assets/images/fuse_logo_white.svg
@@ -1,13 +1,33 @@
-
-