/** * {@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); }
/** * 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); } }
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(); } }