@Override
  @Traced
  public org.vertexium.Authorizations getAuthorizations(
      User user, String... additionalAuthorizations) {
    Set<String> userAuthorizations;
    if (user instanceof SystemUser) {
      userAuthorizations = new HashSet<>();
      userAuthorizations.add(VisalloVisibility.SUPER_USER_VISIBILITY_STRING);
    } else {
      Vertex userVertex = userVertexCache.getIfPresent(user.getUserId());
      if (userVertex != null) {
        userAuthorizations = getAuthorizations(userVertex);
      } else {
        userAuthorizations = null;
      }
    }
    if (userAuthorizations == null) {
      LOGGER.debug("BEGIN getAuthorizations query");
      Vertex userVertex = findByIdUserVertex(user.getUserId());
      userAuthorizations = getAuthorizations(userVertex);
      LOGGER.debug("END getAuthorizations query");
    }

    Set<String> authorizationsSet = new HashSet<>(userAuthorizations);
    Collections.addAll(authorizationsSet, additionalAuthorizations);
    return graph.createAuthorizations(authorizationsSet);
  }
 @Override
 public String getCurrentWorkspaceId(String userId) {
   User user = findById(userId);
   checkNotNull(user, "Could not find user: " + userId);
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   return UserVisalloProperties.CURRENT_WORKSPACE.getPropertyValue(userVertex);
 }
 @Override
 protected void internalSetPrivileges(User user, Set<String> privileges, User authUser) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.PRIVILEGES.setProperty(
       userVertex, Privilege.toString(privileges), VISIBILITY.getVisibility(), authorizations);
   graph.flush();
   userVertexCache.invalidate(user.getUserId());
 }
 @Override
 public User setCurrentWorkspace(String userId, String workspaceId) {
   User user = findById(userId);
   checkNotNull(user, "Could not find user: " + userId);
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.CURRENT_WORKSPACE.setProperty(
       userVertex, workspaceId, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
   return user;
 }
 @Override
 public void internalRemoveAuthorization(User user, String auth, User authUser) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   Set<String> authorizationSet = getAuthorizations(userVertex);
   if (!authorizationSet.contains(auth)) {
     return;
   }
   authorizationSet.remove(auth);
   String authorizationsString = StringUtils.join(authorizationSet, ",");
   UserVisalloProperties.AUTHORIZATIONS.setProperty(
       userVertex, authorizationsString, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
   userVertexCache.invalidate(user.getUserId());
 }
 @Override
 public void setEmailAddress(User user, String emailAddress) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.EMAIL_ADDRESS.setProperty(
       userVertex, emailAddress, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
 }
 @Override
 public void setDisplayName(User user, String displayName) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.DISPLAY_NAME.setProperty(
       userVertex, displayName, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
 }
 @Override
 public void setUiPreferences(User user, JSONObject preferences) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.UI_PREFERENCES.setProperty(
       userVertex, preferences, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
 }
  @Override
  public void recordLogin(User user, String remoteAddr) {
    Vertex userVertex = findByIdUserVertex(user.getUserId());
    ExistingElementMutation<Vertex> m = userVertex.prepareMutation();

    Date currentLoginDate = UserVisalloProperties.CURRENT_LOGIN_DATE.getPropertyValue(userVertex);
    if (currentLoginDate != null) {
      UserVisalloProperties.PREVIOUS_LOGIN_DATE.setProperty(
          m, currentLoginDate, VISIBILITY.getVisibility());
    }

    String currentLoginRemoteAddr =
        UserVisalloProperties.CURRENT_LOGIN_REMOTE_ADDR.getPropertyValue(userVertex);
    if (currentLoginRemoteAddr != null) {
      UserVisalloProperties.PREVIOUS_LOGIN_REMOTE_ADDR.setProperty(
          m, currentLoginRemoteAddr, VISIBILITY.getVisibility());
    }

    UserVisalloProperties.CURRENT_LOGIN_DATE.setProperty(m, new Date(), VISIBILITY.getVisibility());
    UserVisalloProperties.CURRENT_LOGIN_REMOTE_ADDR.setProperty(
        m, remoteAddr, VISIBILITY.getVisibility());

    int loginCount = UserVisalloProperties.LOGIN_COUNT.getPropertyValue(userVertex, 0);
    UserVisalloProperties.LOGIN_COUNT.setProperty(m, loginCount + 1, VISIBILITY.getVisibility());

    m.save(authorizations);
    graph.flush();
  }
 @Override
 public void clearPasswordResetTokenAndExpirationDate(User user) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.PASSWORD_RESET_TOKEN.removeProperty(userVertex, authorizations);
   UserVisalloProperties.PASSWORD_RESET_TOKEN_EXPIRATION_DATE.removeProperty(
       userVertex, authorizations);
   graph.flush();
 }
 @Override
 public void setPasswordResetTokenAndExpirationDate(User user, String token, Date expirationDate) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.PASSWORD_RESET_TOKEN.setProperty(
       userVertex, token, VISIBILITY.getVisibility(), authorizations);
   UserVisalloProperties.PASSWORD_RESET_TOKEN_EXPIRATION_DATE.setProperty(
       userVertex, expirationDate, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
 }
 @Override
 public void setPropertyOnUser(User user, String propertyName, Object value) {
   if (user instanceof SystemUser) {
     throw new VisalloException("Cannot set properties on system user");
   }
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   userVertex.setProperty(propertyName, value, VISIBILITY.getVisibility(), authorizations);
   if (user instanceof VertexiumUser) {
     ((VertexiumUser) user).setProperty(propertyName, value);
   }
 }
 @Override
 public void setPassword(User user, String password) {
   byte[] salt = UserPasswordUtil.getSalt();
   byte[] passwordHash = UserPasswordUtil.hashPassword(password, salt);
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.PASSWORD_SALT.setProperty(
       userVertex, salt, VISIBILITY.getVisibility(), authorizations);
   UserVisalloProperties.PASSWORD_HASH.setProperty(
       userVertex, passwordHash, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
 }
 @Override
 public boolean isPasswordValid(User user, String password) {
   try {
     Vertex userVertex = findByIdUserVertex(user.getUserId());
     return UserPasswordUtil.validatePassword(
         password,
         UserVisalloProperties.PASSWORD_SALT.getPropertyValue(userVertex),
         UserVisalloProperties.PASSWORD_HASH.getPropertyValue(userVertex));
   } catch (Exception ex) {
     throw new RuntimeException("error validating password", ex);
   }
 }
 @Override
 protected void internalDelete(User user) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   graph.softDeleteVertex(userVertex, authorizations);
   graph.flush();
 }