Factor out user validation, use custom errors