@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);
  }
  @Handle
  public ClientApiSuccess handle(
      @Required(name = "graphVertexId") String graphVertexId,
      @Required(name = "propertyKey") String propertyKey,
      @Required(name = "propertyName") String propertyName,
      @ActiveWorkspaceId String workspaceId,
      User user,
      Authorizations authorizations)
      throws Exception {
    OntologyProperty ontologyProperty = ontologyRepository.getRequiredPropertyByIRI(propertyName);

    Vertex vertex = graph.getVertex(graphVertexId, authorizations);

    if (!aclProvider.canDeleteProperty(vertex, propertyKey, propertyName, user)) {
      throw new VisalloAccessDeniedException(
          propertyName + " is not deleteable", user, graphVertexId);
    }

    boolean isComment = VisalloProperties.COMMENT.getPropertyName().equals(propertyName);
    if (isComment && autoPublishComments) {
      workspaceId = null;
    }

    workspaceHelper.deleteProperties(
        vertex, propertyKey, propertyName, ontologyProperty, workspaceId, authorizations, user);

    return VisalloResponse.SUCCESS;
  }
  @Inject
  public VertexiumUserRepository(
      Configuration configuration,
      SimpleOrmSession simpleOrmSession,
      AuthorizationRepository authorizationRepository,
      Graph graph,
      OntologyRepository ontologyRepository,
      UserSessionCounterRepository userSessionCounterRepository,
      WorkQueueRepository workQueueRepository,
      UserNotificationRepository userNotificationRepository,
      LockRepository lockRepository) {
    super(
        configuration,
        simpleOrmSession,
        userSessionCounterRepository,
        workQueueRepository,
        userNotificationRepository,
        lockRepository);
    this.authorizationRepository = authorizationRepository;
    this.graph = graph;

    authorizationRepository.addAuthorizationToGraph(VISIBILITY_STRING);
    authorizationRepository.addAuthorizationToGraph(VisalloVisibility.SUPER_USER_VISIBILITY_STRING);

    Concept userConcept =
        ontologyRepository.getOrCreateConcept(null, USER_CONCEPT_IRI, "visalloUser", null);
    userConceptId = userConcept.getIRI();

    Set<String> authorizationsSet = new HashSet<>();
    authorizationsSet.add(VISIBILITY_STRING);
    authorizationsSet.add(VisalloVisibility.SUPER_USER_VISIBILITY_STRING);
    this.authorizations = graph.createAuthorizations(authorizationsSet);
  }
 @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 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 setDisplayName(User user, String displayName) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.DISPLAY_NAME.setProperty(
       userVertex, displayName, VISIBILITY.getVisibility(), authorizations);
   graph.flush();
 }
 @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
  protected User addUser(
      String username,
      String displayName,
      String emailAddress,
      String password,
      String[] userAuthorizations) {
    username = formatUsername(username);
    displayName = displayName.trim();
    String authorizationsString = StringUtils.join(userAuthorizations, ",");

    byte[] salt = UserPasswordUtil.getSalt();
    byte[] passwordHash = UserPasswordUtil.hashPassword(password, salt);

    String id = GRAPH_USER_ID_PREFIX + graph.getIdGenerator().nextId();
    VertexBuilder userBuilder = graph.prepareVertex(id, VISIBILITY.getVisibility());

    VisalloProperties.CONCEPT_TYPE.setProperty(
        userBuilder, userConceptId, VISIBILITY.getVisibility());
    UserVisalloProperties.USERNAME.setProperty(userBuilder, username, VISIBILITY.getVisibility());
    UserVisalloProperties.DISPLAY_NAME.setProperty(
        userBuilder, displayName, VISIBILITY.getVisibility());
    UserVisalloProperties.CREATE_DATE.setProperty(
        userBuilder, new Date(), VISIBILITY.getVisibility());
    UserVisalloProperties.PASSWORD_SALT.setProperty(userBuilder, salt, VISIBILITY.getVisibility());
    UserVisalloProperties.PASSWORD_HASH.setProperty(
        userBuilder, passwordHash, VISIBILITY.getVisibility());
    UserVisalloProperties.STATUS.setProperty(
        userBuilder, UserStatus.OFFLINE.toString(), VISIBILITY.getVisibility());
    UserVisalloProperties.AUTHORIZATIONS.setProperty(
        userBuilder, authorizationsString, VISIBILITY.getVisibility());
    UserVisalloProperties.PRIVILEGES.setProperty(
        userBuilder, Privilege.toString(getDefaultPrivileges()), VISIBILITY.getVisibility());

    if (emailAddress != null) {
      UserVisalloProperties.EMAIL_ADDRESS.setProperty(
          userBuilder, emailAddress, VISIBILITY.getVisibility());
    }

    User user = createFromVertex(userBuilder.save(this.authorizations));
    graph.flush();

    afterNewUserAdded(user);

    return user;
  }
 @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 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 User setStatus(String userId, UserStatus status) {
   VertexiumUser user = (VertexiumUser) findById(userId);
   checkNotNull(user, "Could not find user: " + userId);
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   UserVisalloProperties.STATUS.setProperty(
       userVertex, status.toString(), VISIBILITY.getVisibility(), authorizations);
   graph.flush();
   user.setUserStatus(status);
   return user;
 }
 @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 User findByPasswordResetToken(String token) {
   return createFromVertex(
       singleOrDefault(
           graph
               .query(authorizations)
               .has(UserVisalloProperties.PASSWORD_RESET_TOKEN.getPropertyName(), token)
               .has(VisalloProperties.CONCEPT_TYPE.getPropertyName(), userConceptId)
               .vertices(),
           null));
 }
 @Traced
 public Vertex findByIdUserVertex(String userId) {
   Vertex userVertex = userVertexCache.getIfPresent(userId);
   if (userVertex != null) {
     return userVertex;
   }
   userVertex = graph.getVertex(userId, authorizations);
   if (userVertex != null) {
     userVertexCache.put(userId, userVertex);
   }
   return userVertex;
 }
 @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 Iterable<User> find(int skip, int limit) {
   return new ConvertingIterable<Vertex, User>(
       graph
           .query(authorizations)
           .has(VisalloProperties.CONCEPT_TYPE.getPropertyName(), userConceptId)
           .skip(skip)
           .limit(limit)
           .vertices()) {
     @Override
     protected User convert(Vertex vertex) {
       return createFromVertex(vertex);
     }
   };
 }
 @Override
 public User findByUsername(String username) {
   username = formatUsername(username);
   Iterable<Vertex> vertices =
       graph
           .query(authorizations)
           .has(UserVisalloProperties.USERNAME.getPropertyName(), username)
           .has(VisalloProperties.CONCEPT_TYPE.getPropertyName(), userConceptId)
           .vertices();
   Vertex userVertex = singleOrDefault(vertices, null);
   if (userVertex == null) {
     return null;
   }
   userVertexCache.put(userVertex.getId(), userVertex);
   return createFromVertex(userVertex);
 }
 @Override
 protected void internalDelete(User user) {
   Vertex userVertex = findByIdUserVertex(user.getUserId());
   graph.softDeleteVertex(userVertex, authorizations);
   graph.flush();
 }