/**
  * {@inheritDoc}
  *
  * @see
  *     org.sakaiproject.nakamura.api.personal.PersonalTrackingStore#recordActivity(java.lang.String,
  *     java.lang.String, java.lang.String, java.lang.String, java.util.Date)
  */
 public void recordActivity(
     String resourceId,
     String resourceType,
     String activityType,
     String userId,
     Calendar timestamp) {
   Session session = null;
   try {
     session = repository.loginAdministrative();
     final ContentManager cm = session.getContentManager();
     final String trackingNodePath = "/activity/" + resourceType + "/" + resourceId;
     Content trackingNode = null;
     if (cm.exists(trackingNodePath)) {
       trackingNode = cm.get(trackingNodePath);
     } else {
       trackingNode = new Content(trackingNodePath, new HashMap<String, Object>());
     }
     if (!trackingNode.hasProperty("count")) {
       trackingNode.setProperty("count", BigDecimal.ZERO);
     }
     if (!trackingNode.hasProperty("sling:resourceType")) {
       trackingNode.setProperty("sling:resourceType", "sakai/resource-activity");
     }
     final String generatedNodeName =
         Base64.encodeBase64URLSafeString(asShorterByteArray(UUID.randomUUID()));
     final String activityNodePath = trackingNodePath + "/" + generatedNodeName;
     Content activityNode = null;
     if (cm.exists(activityNodePath)) {
       activityNode = cm.get(activityNodePath);
     } else {
       activityNode = new Content(activityNodePath, new HashMap<String, Object>());
     }
     BigDecimal activityCount = (BigDecimal) trackingNode.getProperty("count");
     activityNode.setProperty("sling:resourceType", "sakai/resource-update");
     trackingNode.setProperty("count", activityCount.add(BigDecimal.ONE));
     activityNode.setProperty("resourceId", resourceId);
     activityNode.setProperty("resourcetype", resourceType);
     activityNode.setProperty("activitytype", activityType);
     activityNode.setProperty("timestamp", timestamp);
     activityNode.setProperty("userid", userId);
     cm.update(activityNode);
     cm.update(trackingNode);
   } catch (AccessDeniedException e) {
     LOG.error(e.getLocalizedMessage(), e);
   } catch (StorageClientException e) {
     LOG.error(e.getLocalizedMessage(), e);
   } finally {
     if (session != null) {
       try {
         session.logout();
       } catch (ClientPoolException e) {
         LOG.error(e.getLocalizedMessage(), e);
         throw new IllegalStateException(e);
       }
     }
   }
 }
  @Before
  public void before() throws ClientPoolException, StorageClientException, AccessDeniedException {

    javax.jcr.Session jcrSession =
        Mockito.mock(
            javax.jcr.Session.class,
            Mockito.withSettings().extraInterfaces(SessionAdaptable.class));
    session = repository.loginAdministrative("ieb");
    Mockito.when(((SessionAdaptable) jcrSession).getSession()).thenReturn(session);
    Mockito.when(resourceResolver.adaptTo(javax.jcr.Session.class)).thenReturn(jcrSession);
    when(request.getRemoteUser()).thenReturn("ieb");
    when(request.getResourceResolver()).thenReturn(resourceResolver);

    servlet = new LiteUserExistsServlet();
  }
  @Before
  public void setUp() throws Exception {
    provider = new MyRelatedGroupsPropertyProvider(searchServiceFactory);
    when(request.getRemoteUser()).thenReturn("user1");

    when(repo.loginAdministrative()).thenReturn(session);
    when(session.getAuthorizableManager()).thenReturn(authMgr);
    when(authMgr.findAuthorizable("user1")).thenReturn(auth1);

    Group group1 = mock(Group.class);
    when(group1.getId()).thenReturn("group1");
    when(group1.getProperty(GROUP_TITLE_PROPERTY)).thenReturn("Group 1 Test");
    when(group1.getProperty("sakai:tag-uuid")).thenReturn(new String[] {"123-456"});

    when(auth1.memberOf(authMgr)).thenReturn(Sets.newHashSet(group1).iterator());

    when(searchServiceFactory.getSearchResultSet(eq(request), any(Query.class))).thenReturn(rs);
  }
Example #4
0
  /**
   * Writes commentCount of content
   *
   * @param node
   * @param session
   * @param write
   * @throws RepositoryException
   * @throws JSONException
   */
  public static void writeCommentCountProperty(
      Content content,
      org.sakaiproject.nakamura.api.lite.Session session,
      JSONWriter writer,
      Repository repository)
      throws StorageClientException, JSONException {

    int commentCount = 0;
    String COMMENTCOUNT = "commentCount";

    if (content.hasProperty(COMMENTCOUNT)) {
      commentCount = (Integer) content.getProperty(COMMENTCOUNT);
    } else {
      // no commentCount property on Content, then evaluate count and add property
      Content comments = null;
      org.sakaiproject.nakamura.api.lite.Session adminSession = null;
      try {
        comments = session.getContentManager().get(content.getPath() + "/comments");
        if (comments != null) {
          commentCount = Iterables.size(comments.listChildPaths());
        }
        content.setProperty(COMMENTCOUNT, commentCount);
        // save property
        adminSession = repository.loginAdministrative();
        ContentManager adminContentManager = adminSession.getContentManager();
        adminContentManager.update(content);
      } catch (org.sakaiproject.nakamura.api.lite.accesscontrol.AccessDeniedException e) {
        log.error(e.getMessage(), e);
      } finally {
        if (adminSession != null) {
          try {
            adminSession.logout();
          } catch (Exception e) {
            log.error("Could not logout administrative session.");
          }
        }
      }
    }
    writer.key(COMMENTCOUNT);
    writer.value(commentCount);
  }
  @SuppressWarnings("unchecked")
  public void onMessage(Message message) {
    log.debug("Receiving a message on {} : {}", SyncJMSMessageProducer.QUEUE_NAME, message);
    try {

      String topic = message.getJMSType();
      String groupId = (String) message.getStringProperty("path");

      String operation = "UNKNOWN";

      // A group was DELETED
      if ("org/sakaiproject/nakamura/lite/authorizables/DELETE".equals(topic)
          && config.getDeletesEnabled()) {
        Map<String, Object> attributes =
            (Map<String, Object>) message.getObjectProperty(StoreListener.BEFORE_EVENT_PROPERTY);
        grouperManager.deleteGroup(groupId, attributes);
        operation = "DELETED";
      }

      // A new group was ADDED or an existing group was UPDATED
      if ("org/sakaiproject/nakamura/lite/authorizables/ADDED".equals(topic)
          || "org/sakaiproject/nakamura/lite/authorizables/UPDATED".equals(topic)) {
        // These events should be under org/sakaiproject/nakamura/lite/authorizables/UPDATED
        // http://jira.sakaiproject.org/browse/KERN-1795
        String membersAdded =
            (String) message.getStringProperty(GrouperEventUtils.MEMBERS_ADDED_PROP);
        if (membersAdded != null) {
          // membership adds can be attached to the same event for the group add.
          grouperManager.createGroup(groupId, config.getGroupTypes());
          grouperManager.addMemberships(
              groupId, Arrays.asList(StringUtils.split(membersAdded, ",")));
          operation = "ADD_MEMBERS";
        }

        String membersRemoved =
            (String) message.getStringProperty(GrouperEventUtils.MEMBERS_REMOVED_PROP);
        if (membersRemoved != null) {
          grouperManager.removeMemberships(
              groupId, Arrays.asList(StringUtils.split(membersRemoved, ",")));
          operation = "REMOVE_MEMBERS";
        }

        if (membersAdded == null && membersRemoved == null) {
          org.sakaiproject.nakamura.api.lite.Session repositorySession =
              repository.loginAdministrative();
          AuthorizableManager am = repositorySession.getAuthorizableManager();
          Group group = (Group) am.findAuthorizable(groupId);
          repositorySession.logout();

          if (groupId.startsWith(ContactsGrouperNameProviderImpl.CONTACTS_GROUPID_PREFIX)) {
            // TODO Why are we not getting added and removed properties on the Message
            grouperManager.createGroup(groupId, null);
            grouperManager.addMemberships(groupId, Arrays.asList(group.getMembers()));
            operation = "UPDATE CONTACTS";
          } else {
            grouperManager.createGroup(groupId, config.getGroupTypes());
            grouperManager.addMemberships(groupId, Arrays.asList(group.getMembers()));
            operation = "CREATE";
          }
        }
      }

      // The message was processed successfully. No exceptions were thrown.
      // We acknowledge the message and its removed from the queue
      message.acknowledge();

      // We got a message that we didn't know what to do with.
      if (operation.equals("UNKNOWN")) {
        log.error(
            "I don't know what to do with this topic: {}. Turn on debug logs to see the message.",
            topic);
        log.debug(message.toString());
      } else {
        log.info("Successfully processed and acknowledged. {}, {}", operation, groupId);
        log.debug(message.toString());
      }

    } catch (JMSException jmse) {
      log.error("JMSException while processing message.", jmse);
    } catch (Exception e) {
      log.error("Exception while processing message.", e);
    }
  }
Example #6
0
  public void createActivity(
      Session session, Content targetLocation, String userId, ActivityServiceCallback callback)
      throws AccessDeniedException, StorageClientException, ServletException, IOException {
    if (userId == null) {
      userId = session.getUserId();
    }
    if (!userId.equals(session.getUserId()) && !User.ADMIN_USER.equals(session.getUserId())) {
      throw new IllegalStateException(
          "Only Administrative sessions may act on behalf of another user for activities");
    }
    ContentManager contentManager = session.getContentManager();
    // create activityStore if it does not exist
    String path = StorageClientUtils.newPath(targetLocation.getPath(), ACTIVITY_STORE_NAME);
    if (!contentManager.exists(path)) {
      contentManager.update(
          new Content(
              path,
              ImmutableMap.<String, Object>of(
                  SLING_RESOURCE_TYPE_PROPERTY, ACTIVITY_STORE_RESOURCE_TYPE)));
      // inherit ACL from the target node, but let logged-in users write activities
      session
          .getAccessControlManager()
          .setAcl(
              Security.ZONE_CONTENT,
              path,
              new AclModification[] {
                new AclModification(
                    AclModification.grantKey(Group.EVERYONE),
                    Permissions.CAN_WRITE.getPermission(),
                    Operation.OP_AND)
              });
    }
    // create activity within activityStore
    String activityPath = StorageClientUtils.newPath(path, ActivityUtils.createId());
    String activityFeedPath = StorageClientUtils.newPath(targetLocation.getPath(), "activityFeed");

    if (!contentManager.exists(activityFeedPath)) {
      contentManager.update(new Content(activityFeedPath, null));
    }
    if (!contentManager.exists(activityPath)) {
      contentManager.update(
          new Content(
              activityPath,
              ImmutableMap.of(
                  JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY,
                  (Object) ActivityConstants.ACTIVITY_ITEM_RESOURCE_TYPE)));
    }

    Content activtyNode = contentManager.get(activityPath);
    callback.processRequest(activtyNode);

    activtyNode = contentManager.get(activityPath);
    activtyNode.setProperty(PARAM_ACTOR_ID, userId);
    activtyNode.setProperty(ActivityConstants.PARAM_SOURCE, targetLocation.getPath());

    Session adminSession = repository.loginAdministrative();
    List<String> routesStr = new LinkedList<String>();
    List<String> readers = new LinkedList<String>();
    try {
      List<ActivityRoute> routes =
          activityRouterManager.getActivityRoutes(activtyNode, adminSession);
      if (routes != null) {
        for (ActivityRoute route : routes) {
          routesStr.add(route.getDestination());
          if (route.getReaders() != null && route.getReaders().length > 0) {
            readers.addAll(Arrays.asList(route.getReaders()));
          }
        }
      }

      // store the routes as child content of the activity so we may lock it down to admin. It's
      // common for
      // the activity to be stored within the context of the content to which it pertains (e.g.,
      // within the
      // pooled content item on which the user performed the activity), therefore we could expose
      // user
      // activity routes there -- that is an exposure of potentially sensitive content such as who
      // the user's
      // connections are.
      String routesPath =
          StorageClientUtils.newPath(activtyNode.getPath(), ActivityConstants.PARAM_ROUTES);
      contentManager.update(
          new Content(
              routesPath,
              ImmutableMap.<String, Object>of(
                  ActivityConstants.PARAM_ROUTES,
                  routesStr.toArray(new String[routesStr.size()]))));
      adminSession
          .getAccessControlManager()
          .setAcl(
              Security.ZONE_CONTENT,
              routesPath,
              new AclModification[] {
                new AclModification(
                    AclModification.denyKey(User.ANON_USER),
                    Permissions.ALL.getPermission(),
                    Operation.OP_REPLACE),
                new AclModification(
                    AclModification.denyKey(Group.EVERYONE),
                    Permissions.ALL.getPermission(),
                    Operation.OP_REPLACE),
                new AclModification(
                    AclModification.denyKey(userId),
                    Permissions.ALL.getPermission(),
                    Operation.OP_REPLACE)
              });

      if (!readers.isEmpty()) {
        AclModification[] readerAcls = new AclModification[readers.size()];
        int i = 0;
        for (String reader : readers) {
          // ensure all the necessary readers/routes can read the activity
          readerAcls[i] =
              new AclModification(
                  AclModification.grantKey(reader),
                  Permissions.CAN_READ.getPermission(),
                  Operation.OP_OR);
          i++;
        }

        adminSession
            .getAccessControlManager()
            .setAcl(Security.ZONE_CONTENT, activtyNode.getPath(), readerAcls);
      }
    } finally {
      SparseUtils.logoutQuietly(adminSession);
    }

    // store the activity node
    contentManager.update(activtyNode);

    // post the asynchronous OSGi event
    final Dictionary<String, String> properties = new Hashtable<String, String>();
    properties.put(UserConstants.EVENT_PROP_USERID, userId);
    properties.put(ActivityConstants.EVENT_PROP_PATH, activityPath);
    properties.put("path", activityPath);
    properties.put("resourceType", ActivityConstants.ACTIVITY_ITEM_RESOURCE_TYPE);
    EventUtils.sendOsgiEvent(properties, LITE_EVENT_TOPIC, eventAdmin);
  }
  public synchronized void migrate(boolean dryRun, int limit, boolean reindexAll, Feedback feedback)
      throws ClientPoolException, StorageClientException, AccessDeniedException, IOException,
          PropertyMigrationException {
    SessionImpl session = (SessionImpl) repository.loginAdministrative();
    StorageClient client = session.getClient();
    FileRedoLogger migrateRedoLog = new FileRedoLogger(redoLogLocation, maxLogFileSize, feedback);
    client.setStorageClientListener(migrateRedoLog);
    try {
      if (client instanceof JDBCStorageClient) {
        JDBCStorageClient jdbcClient = (JDBCStorageClient) client;
        String keySpace = configuration.getKeySpace();

        Indexer indexer = jdbcClient.getIndexer();

        PropertyMigrator[] propertyMigrators = propertyMigratorTracker.getPropertyMigrators();

        DependencySequence migratorDependencySequence =
            getMigratorSequence(session, propertyMigrators);

        for (PropertyMigrator p : migratorDependencySequence) {
          LOGGER.info("DryRun:{} Using Property Migrator {} ", dryRun, p);
          feedback.log("DryRun:{0} Using Property Migrator {1} ", dryRun, p);
        }
        for (PropertyMigrator p : migratorDependencySequence.getUnresolved()) {
          LOGGER.info("DryRun:{} Unresolved Property Migrator {} ", dryRun, p);
          feedback.log("DryRun:{0} Unresolved Property Migrator {1} ", dryRun, p);
        }
        for (Entry<String, Object> p : migratorDependencySequence.getAlreadyRun().entrySet()) {
          LOGGER.info("DryRun:{} Migrator Last Run {} ", dryRun, p);
          feedback.log("DryRun:{0} Migrator Last Run {1} ", dryRun, p);
        }
        if (migratorDependencySequence.hasUnresolved()) {
          throw new PropertyMigrationException(
              "There are unresolved dependencies " + migratorDependencySequence.getUnresolved());
        }
        CacheAwareMigrationManager cacheAwareMigrationManager =
            new CacheAwareMigrationManager(
                jdbcClient, session.getCache(configuration.getAuthorizableColumnFamily()));
        reindex(
            dryRun,
            jdbcClient,
            cacheAwareMigrationManager,
            keySpace,
            configuration.getAuthorizableColumnFamily(),
            indexer,
            migratorDependencySequence,
            new IdExtractor() {

              public String getKey(Map<String, Object> properties) {
                if (properties.containsKey(Authorizable.ID_FIELD)) {
                  return (String) properties.get(Authorizable.ID_FIELD);
                }
                return null;
              }
            },
            limit,
            feedback,
            reindexAll);

        cacheAwareMigrationManager =
            new CacheAwareMigrationManager(
                jdbcClient, session.getCache(configuration.getContentColumnFamily()));
        reindex(
            dryRun,
            jdbcClient,
            cacheAwareMigrationManager,
            keySpace,
            configuration.getContentColumnFamily(),
            indexer,
            migratorDependencySequence,
            new IdExtractor() {

              public String getKey(Map<String, Object> properties) {
                if (properties.containsKey(BlockSetContentHelper.CONTENT_BLOCK_ID)) {
                  // blocks of a bit stream
                  return (String) properties.get(BlockSetContentHelper.CONTENT_BLOCK_ID);
                } else if (properties.containsKey(Content.UUID_FIELD)) {
                  // a content item and content block item
                  return (String) properties.get(Content.UUID_FIELD);
                } else if (properties.containsKey(Content.STRUCTURE_UUID_FIELD)) {
                  // a structure item
                  return (String) properties.get(Content.PATH_FIELD);
                }
                return null;
              }
            },
            limit,
            feedback,
            reindexAll);

        cacheAwareMigrationManager =
            new CacheAwareMigrationManager(
                jdbcClient, session.getCache(configuration.getAclColumnFamily()));
        reindex(
            dryRun,
            jdbcClient,
            cacheAwareMigrationManager,
            keySpace,
            configuration.getAclColumnFamily(),
            indexer,
            migratorDependencySequence,
            new IdExtractor() {
              public String getKey(Map<String, Object> properties) {
                if (properties.containsKey(AccessControlManagerImpl._KEY)) {
                  return (String) properties.get(AccessControlManagerImpl._KEY);
                }
                return null;
              }
            },
            limit,
            feedback,
            reindexAll);

        saveMigratorSequence(session, migratorDependencySequence);

      } else {
        LOGGER.warn("This class will only re-index content for the JDBCStorageClients");
      }
    } finally {
      client.setStorageClientListener(null);
      migrateRedoLog.close();
      session.logout();
    }
  }