I would tweak it a little bit.
The first thing that jumps out is you have the user address inside the struct. That will be redundant because you'll want to keep track of keys some other way. You'll want to look up by key, for example. In that, you'll already know the key you want to look up, right? No need to store it again inside each struct.
I noticed you are storing hashes, so I go forward on the assumption that there will be some offchain storage of meta data. Even so, you might (usually) have some additional on-chain fields. How to know the difference? If the contract needs access to a field in order to perform some in-contract logic, then the field belongs in the struct.
I made the key list public so a client can enumerate the keys and added a function to get a quick count, because raising an error is a nasty way to discover the list length, in my opinion.
pragma solidity ^0.4.17;
contract UserDetails {
struct UserStruct {
string fileHash;
uint userListPointer;
// you may continue with other non-key fields that are needed for contract logic
}
// unique identifiers
address[] public userList;
mapping(address=>UserStruct) public userStructs;
function isUser(address userAddress) public view returns(bool isIndeed) {
if(userList.length ==0) return false;
return userList[userStructs[userAddress].userListPointer] == userAddress;
}
function addUserDetail(string hash,address userAddress) public returns (bool) {
require(!isUser(userAddress));
UserStruct memory usr;
usr.fileHash = hash;
usr.userListPointer = userList.push(userAddress) - 1;
userStructs[userAddress] = usr;
}
function getUserCount() public view returns(uint count) {
return userList.length;
}
}
You can find some related patterns here: Are there well-solved and simple storage patterns for Solidity?
And a full explainer that coincidentally uses Users for the example over here: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a
Hope it helps.