diff --git a/contracts/Forum.sol b/contracts/Forum.sol
index eef2e82..0fc71f3 100644
--- a/contracts/Forum.sol
+++ b/contracts/Forum.sol
@@ -1,56 +1,62 @@
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
contract Forum {
- //----------------------------------------USER----------------------------------------
+ //----------------------------------------AUTHENTICATION----------------------------------------
struct User {
- string userName; // TODO: set an upper bound instead of arbitrary string
+ string username; // TODO: set an upper bound instead of arbitrary string
// TODO: orbitDBAddress;
uint[] topicIDs; // IDs of the topics the user created
uint[] postIDs; // IDs of the posts the user created
+ bool signedUp; // Helper variable for hasUserSignedUp()
}
mapping (address => User) users;
mapping (string => address) userAddresses;
- event UserSignedUp(
- string userName
- );
+ event UserSignedUp(string username, address userAddress);
+ event UsernameUpdated(string newName, string oldName,address userAddress);
- function signUp(string userName) public returns (bool) { // Also allows user to update his name - TODO: his previous name will appear as taken
- require(!isUserNameTaken(userName));
- users[msg.sender] = User(userName, new uint[](0), new uint[](0));
- userAddresses[userName] = msg.sender;
- emit UserSignedUp(userName);
+ function signUp(string username) public returns (bool) {
+ require (!hasUserSignedUp(msg.sender), "User has already signed up.");
+ require(!isUserNameTaken(username), "Username is already taken.");
+ users[msg.sender] = User(username, new uint[](0), new uint[](0), true);
+ userAddresses[username] = msg.sender;
+ emit UserSignedUp(username, msg.sender);
return true;
}
- function login() public view returns (string) {
- require (hasUserSignedUp(msg.sender));
- return users[msg.sender].userName;
+ function updateUsername(string newUsername) public returns (bool) {
+ require (hasUserSignedUp(msg.sender), "User hasn't signed up yet.");
+ require(!isUserNameTaken(newUsername), "Username is already taken.");
+ string memory oldUsername = getUsername(msg.sender);
+ delete userAddresses[users[msg.sender].username];
+ users[msg.sender].username = newUsername;
+ userAddresses[newUsername] = msg.sender;
+ emit UsernameUpdated(newUsername, oldUsername, msg.sender);
+ return true;
}
function getUsername(address userAddress) public view returns (string) {
- return users[userAddress].userName;
+ return users[userAddress].username;
}
- function getUserAddress(string userName) public view returns (address) {
- return userAddresses[userName];
+ function getUserAddress(string username) public view returns (address) {
+ return userAddresses[username];
}
function hasUserSignedUp(address userAddress) public view returns (bool) {
- if (bytes(getUsername(userAddress)).length!=0)
- return true;
- return false;
+ return users[userAddress].signedUp;
}
- function isUserNameTaken(string userName) public view returns (bool) {
- if (getUserAddress(userName)!=0)
+ function isUserNameTaken(string username) public view returns (bool) {
+ if (getUserAddress(username)!=address(0))
return true;
return false;
}
- //----------------------------------------TOPIC----------------------------------------
+
+ //----------------------------------------POSTING----------------------------------------
struct Topic {
uint topicID;
address author;
diff --git a/src/App.js b/src/App.js
index 45d9e02..f51c726 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,7 +4,7 @@ import React, { Component } from 'react'
import './css/oswald.css'
import './css/open-sans.css'
import './css/pure-min.css'
-import './App.css'
+import './css/App.css'
class App extends Component {
render() {
diff --git a/src/containers/AuthWrapperContainer.js b/src/containers/AuthWrapperContainer.js
new file mode 100644
index 0000000..ce2ad11
--- /dev/null
+++ b/src/containers/AuthWrapperContainer.js
@@ -0,0 +1,48 @@
+import { drizzleConnect } from 'drizzle-react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+const contract = "Forum";
+const method = "hasUserSignedUp";
+
+class AuthWrapperContainer extends Component {
+ constructor(props, context) {
+ super(props);
+
+ this.contracts = context.drizzle.contracts;
+
+ this.dataKey = this.contracts[contract].methods[method].cacheCall(...[this.props.accounts[0]]);
+ }
+
+ render() {
+ // Contract is not yet intialized.
+ if(!this.props.contracts[contract].initialized)
+ return (null);
+
+ // If the cache key we received earlier isn't in the store yet; the initial value is still being fetched.
+ if(!(this.dataKey in this.props.contracts[contract][method]))
+ return (null);
+
+ let userHasSignedUp = this.props.contracts[contract][method][this.dataKey].value;
+ const authRender = this.props.authRender;
+ const guestRender = this.props.guestRender;
+
+ if (userHasSignedUp)
+ return(
{authRender}
);
+
+ return({guestRender}
);
+ }
+}
+
+AuthWrapperContainer.contextTypes = {
+ drizzle: PropTypes.object
+};
+
+const mapStateToProps = state => {
+ return {
+ accounts: state.accounts,
+ contracts: state.contracts,
+ }
+};
+
+export default drizzleConnect(AuthWrapperContainer, mapStateToProps)
\ No newline at end of file
diff --git a/src/containers/Menu.js b/src/containers/Menu.js
deleted file mode 100644
index e4be872..0000000
--- a/src/containers/Menu.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { drizzleConnect } from 'drizzle-react'
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-
-const contract = "Forum";
-const method = "hasUserSignedUp";
-
-class Menu extends Component {
- constructor(props, context) {
- super(props);
-
- this.contracts = context.drizzle.contracts;
-
- // Get the contract ABI
- const abi = this.contracts[contract].abi;
-
- // Fetch initial value from chain and return cache key for reactive updates.
- let methodArgs = this.props.methodArgs ? this.props.methodArgs : [];
- this.dataKey = this.contracts[contract].methods[method].cacheCall(...methodArgs);
-
- // Iterate over abi for correct function.
- for (let i = 0; i < abi.length; i++) {
- if (abi[i].name === this.props.method) {
- this.fnABI = abi[i];
- break
- }
- }
- }
-
- render() {
- // Contract is not yet intialized.
- if(!this.props.contracts[contract].initialized) {
- return (
-
- )
- }
-
- // If the cache key we received earlier isn't in the store yet; the initial value is still being fetched.
- if(!(this.dataKey in this.props.contracts[contract][method])) {
- return (
-
- )
- }
-
- let displayData = this.props.contracts[contract][method][this.dataKey].value;
-
- if (displayData) {
- return(
- User has signed up!
- )
- }
-
- return(
- User doesn't exist!
- )
- }
-}
-
-Menu.contextTypes = {
- drizzle: PropTypes.object
-};
-
-const mapStateToProps = state => {
- return {
- contracts: state.contracts
- }
-};
-
-export default drizzleConnect(Menu, mapStateToProps)
\ No newline at end of file
diff --git a/src/containers/UsernameFormContainer.js b/src/containers/UsernameFormContainer.js
new file mode 100644
index 0000000..469a47f
--- /dev/null
+++ b/src/containers/UsernameFormContainer.js
@@ -0,0 +1,103 @@
+import { drizzleConnect } from 'drizzle-react'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import AuthWrapperContainer from './AuthWrapperContainer'
+
+const contract = "Forum";
+const signUpMethod = "signUp";
+const updateUsernameMethod ="updateUsername";
+
+class UsernameFormContainer extends Component {
+ constructor(props, context) {
+ super(props);
+
+ this.handleSignUp = this.handleSignUp.bind(this);
+ this.handleSignUpInputChange = this.handleSignUpInputChange.bind(this);
+
+ this.handleUsernameUpdate = this.handleUsernameUpdate.bind(this);
+ this.handleUpdateUsernameInputChange = this.handleUpdateUsernameInputChange.bind(this);
+
+ this.contracts = context.drizzle.contracts;
+
+ // Get the contract ABI
+ const abi = this.contracts[contract].abi;
+
+
+ this.inputs = {signUp:[], updateUsername:[]};
+ let initialState = {signUp:{}, updateUsername:{}};
+
+ // Iterate over abi for correct function.
+ for (let i = 0; i < abi.length; i++) {
+ if ((abi[i].name === signUpMethod)) {
+ this.inputs.signUp = abi[i].inputs;
+
+ for (let i = 0; i < this.inputs.signUp.length; i++) {
+ initialState.signUp[this.inputs.signUp[i].name] = '';
+ }
+
+ }
+ else if ((abi[i].name === updateUsernameMethod)) {
+ this.inputs.updateUsername = abi[i].inputs;
+
+ for (let i = 0; i < this.inputs.updateUsername.length; i++) {
+ initialState.updateUsername[this.inputs.updateUsername[i].name] = '';
+ }
+
+ }
+ }
+ console.dir(initialState);
+ this.state = initialState;
+ }
+
+ handleSignUp() {
+ this.contracts[contract].methods[signUpMethod].cacheSend(...Object.values(this.state.signUp));
+ }
+
+ handleUsernameUpdate() {
+ this.contracts[contract].methods[updateUsernameMethod].cacheSend(...Object.values(this.state.updateUsername));
+ }
+
+ handleSignUpInputChange(event) {
+ this.setState({ signUp: { ...this.state.signUp, [event.target.name]: event.target.value} });
+ }
+
+ handleUpdateUsernameInputChange(event) {
+ this.setState({ updateUsername: { ...this.state.updateUsername, [event.target.name]: event.target.value} });
+ }
+
+
+ render() {
+ let signUp = this.inputs.signUp[0].name; //username
+ let updateUsername = this.inputs.updateUsername[0].name; //newUsername
+ return (
+
+
+
+
+ }
+ guestRender={
+
+ }
+ />
+
+
+ )
+ }
+}
+
+UsernameFormContainer.contextTypes = {
+ drizzle: PropTypes.object
+};
+
+const mapStateToProps = state => {
+ return {
+ contracts: state.contracts
+ }
+};
+
+export default drizzleConnect(UsernameFormContainer, mapStateToProps)
\ No newline at end of file
diff --git a/src/App.css b/src/css/App.css
similarity index 100%
rename from src/App.css
rename to src/css/App.css
diff --git a/src/index.css b/src/css/index.css
similarity index 100%
rename from src/index.css
rename to src/css/index.css
diff --git a/src/index.js b/src/index.js
index 2ffbcc6..7877e8d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -12,6 +12,8 @@ import { LoadingContainer } from 'drizzle-react-components'
import store from './store'
import drizzleOptions from './drizzleOptions'
+import './css/index.css'
+
// Initialize react-router-redux.
const history = syncHistoryWithStore(browserHistory, store);
diff --git a/src/layouts/home/Home.js b/src/layouts/home/Home.js
index eade9af..2b68cc5 100644
--- a/src/layouts/home/Home.js
+++ b/src/layouts/home/Home.js
@@ -1,6 +1,6 @@
import React, { Component } from 'react'
-import { AccountData, ContractData, ContractForm } from 'drizzle-react-components'
-import Menu from './../../containers/Menu'
+import { AccountData, ContractData } from 'drizzle-react-components'
+import UsernameFormContainer from '../../containers/UsernameFormContainer'
class Home extends Component {
render() {
@@ -15,8 +15,7 @@ class Home extends Component {
Account
Username:
-
-
+