pragma solidity ^0.4.24;




contract Authentication {
  struct User {
    bytes32 name;
    uint256 created_at;
  }
  
  event UserCreated(address indexed _address, bytes32 _name, uint256 _created_at);
  event UserUpdated(address indexed _address, bytes32 _name);
  event UserDeleted(address indexed _address);
  
  
  mapping (address => User) private users;
  
  
  address[] public allUsers;
  modifier onlyExistingUser {
    

    require(!(users[msg.sender].name == 0x0));
    _;
  }

  modifier onlyValidName(bytes32 name) {
    

    require(!(name == 0x0));
    _;
  }
  
  
  function login() 
  public
  view 
  onlyExistingUser
  returns (bytes32) {
    return (users[msg.sender].name);
  }
  
  
  
  
  
  
  
  function signup(bytes32 name)
  public
  payable
  onlyValidName(name)
  returns (bytes32) {

    if (users[msg.sender].name == 0x0)
    {
        users[msg.sender].name = name;
	    users[msg.sender].created_at = now;
        
        allUsers.push(msg.sender);
        emit UserCreated(msg.sender,name,now);
        return (users[msg.sender].name);
    }

    return (users[msg.sender].name);
  }
  
  
  
  
  function update(bytes32 name)
  public
  payable
  onlyValidName(name)
  onlyExistingUser
  returns (bytes32) {
    

    if (users[msg.sender].name != 0x0)
    {
        users[msg.sender].name = name;
        
        emit UserUpdated(msg.sender,name);
 
        return (users[msg.sender].name);
    }
  }
  
  
  function destroy () 
  public 
  onlyExistingUser {
    delete users[msg.sender];
    emit UserDeleted(msg.sender);
  }
}