Skip to content

Commit

Permalink
DASH-324 setup cron job to sync dashboard users with current sakai si…
Browse files Browse the repository at this point in the history
…te users

git-svn-id: https://source.sakaiproject.org/svn/dashboard/trunk@314882 66ffb92e-73f9-0310-93c1-f5514f145a0a
  • Loading branch information
zqian committed Oct 24, 2014
1 parent 24773e1 commit dbf4b1e
Show file tree
Hide file tree
Showing 11 changed files with 455 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,9 @@ public interface DashboardCommonLogic extends DashboardLogic, DashboardUserLogic
* Check for admin dashboard configuration changes
*/
public void checkForAdminChanges();

/**
* Synchronize the dashboard links table users with current site users
*/
public void syncDashboardUsersWithSiteUsers();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.HashMap;

import org.sakaiproject.dash.logic.TaskLock;
import org.sakaiproject.dash.model.AvailabilityCheck;
Expand Down Expand Up @@ -584,4 +585,19 @@ public void setConfigProperty(String propertyName,
*/
public boolean deleteRepeatingEvent(Long id);

/**
* construct HashMap
* keyed with context id
* and value is set of user ids that has rows in DASHBOARD_CALENDAR_LINK table
* @return HashMap object
*/
public HashMap<String, Set<String>> getDashboardCalendarContextUserMap();

/**
* construct HashMap
* keyed with context id
* and value is set of user ids that has rows in DASHBOARD_NEWS_LINK table
* @return HashMap object
*/
public HashMap<String, Set<String>> getDashboardNewsContextUserMap();
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Collection;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
Expand All @@ -51,7 +54,9 @@
import org.sakaiproject.dash.dao.mapper.RepeatingCalendarItemMapper;
import org.sakaiproject.dash.dao.mapper.SourceTypeMapper;
import org.sakaiproject.dash.dao.mapper.TaskLockMapper;
import org.sakaiproject.dash.dao.mapper.ContextUserMapper;
import org.sakaiproject.dash.logic.TaskLock;
import org.sakaiproject.dash.logic.DashboardLogic;
import org.sakaiproject.dash.model.AvailabilityCheck;
import org.sakaiproject.dash.model.CalendarItem;
import org.sakaiproject.dash.model.CalendarLink;
Expand Down Expand Up @@ -2281,4 +2286,75 @@ public boolean deleteRepeatingEvent(Long id) {
return false;
}
}

/* (non-Javadoc)
* @see org.sakaiproject.dash.dao.DashboardDao#getDashboardCalendarContextUserMap()
*/
public HashMap<String, Set<String>> getDashboardCalendarContextUserMap()
{
return getDashboardContextUserMap("select.context.user.from.calendar.link");
}

/* (non-Javadoc)
* @see org.sakaiproject.dash.dao.DashboardDao#getDashboardNewsContextUserMap()
*/
public HashMap<String, Set<String>> getDashboardNewsContextUserMap()
{
return getDashboardContextUserMap("select.context.user.from.news.link");
}

/**
* construct HashMap,
* keyed with context id,
* value is set of user ids that has links(calendarlink, newslink) in dashboard
* @param the sql name
* @return HashMap object
*/
private HashMap<String, Set<String>> getDashboardContextUserMap(String sqlName)
{
HashMap<String, Set<String>> dashboardUserMap = new HashMap<String, Set<String>>();
String sql = getStatement(sqlName);
try {
List<String> contextUsersList = (List<String>) getJdbcTemplate().query(sql,
new ContextUserMapper()
);

if (contextUsersList != null)
{
for(String contextUser : contextUsersList)
{
// the string returned from db query is of format context id + " " + user id
// need to parse it out and form HashMap
String[] parts = contextUser.split(" ");
if (parts.length == 2)
{
// parts: context id (site id) and user id
String context_id = parts[0];
String user_id = parts[1];
if (dashboardUserMap.containsKey(context_id))
{
// get the current set and add user id into it
Set<String> current = dashboardUserMap.get(context_id);
current.add(user_id);
dashboardUserMap.put(context_id, current);
}
else
{
// add the new key
Set<String> current = new HashSet<String>();
current.add(user_id);
dashboardUserMap.put(context_id, current);
}

}
}
}
} catch (EmptyResultDataAccessException ex) {
log.debug("getDashboardContextUserMap: Empty result executing query: " + sqlName + " " + ex.getClass() + ":" + ex.getMessage());
} catch (DataAccessException ex) {
log.warn("getDashboardContextUserMap: Error executing query: " + sqlName + " " + ex.getClass() + ":" + ex.getMessage());
}

return dashboardUserMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**********************************************************************************
* $URL: $
* $Id: $
***********************************************************************************
*
* Copyright (c) 2011 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/

package org.sakaiproject.dash.dao.mapper;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.sakaiproject.dash.model.Context;
import org.springframework.jdbc.core.RowMapper;

/**
* Mapper for the "context_users" string returned
*/
public class ContextUserMapper implements RowMapper
{

public String mapRow(ResultSet rs, int rowNum) throws SQLException {
String rv = "";
try {
rv = rs.getString("context_users");
} catch (Exception e) {
System.out.println(this + " =============== " + e + " ===============");
e.printStackTrace(System.out);
if(e instanceof SQLException) {
throw (SQLException) e;
}
}
return rv;
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* $URL: $
* $Id: $
*
* Copyright (c) 2006-2009 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sakaiproject.dash.jobs;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
* this job is to find out the up-to-date user enrolled sites
* remove site dashboard items if the user no longer belongs to the site
* or add site dashboard items if the user is added to the site
* @author zqian
*
*/
public class DashSyncUserSitesJob extends DashQuartzJob {
private Log logger = LogFactory.getLog(DashSyncUserSitesJob.class);

//Matches the bean id
final static String beanId = "dashSyncUserSitesJob";

//Matches the jobName
final static String jobName = "Dashboard Synchronize Dashboard Link Users with Site Users Job";

public void init() {
super.init();
logger.info(this + " init()");
}

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String quartzServer = sakaiProxy.getConfigParam("dashboard_quartzServer", null);
String serverName = sakaiProxy.getServerId();
if (quartzServer != null && serverName != null && quartzServer.equals(serverName))
{
logger.info(this + " execute: " + getConfigMessage());

try {
dashboardCommonLogic.syncDashboardUsersWithSiteUsers();
} catch (Exception e) {
logger.warn(this + "execute error: " , e);
}
}
}

}


Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.Collection;

import net.sf.ehcache.Cache;

Expand Down Expand Up @@ -64,6 +65,8 @@
import org.sakaiproject.util.FormattedText;
import org.sakaiproject.util.ResourceLoader;

import org.sakaiproject.authz.api.AuthzGroupService;

/**
*
*
Expand Down Expand Up @@ -162,6 +165,11 @@ public void setDashboardUserLogic(DashboardUserLogic dashboardUserLogic) {
this.dashboardUserLogic = dashboardUserLogic;
}

protected AuthzGroupService authzGroupService;
public void setAuthzGroupService(AuthzGroupService authzGroupService) {
this.authzGroupService = authzGroupService;
}

protected Cache cache;

public void setCache(Cache cache) {
Expand Down Expand Up @@ -1665,4 +1673,113 @@ public SecurityAdvice isAllowed(String userId, String function, String reference
}
};
}

/**
* {@inheritDoc}
*/
public void syncDashboardUsersWithSiteUsers()
{
logger.info(this + ".syncDashboardUsersWithSiteUsers start " + serverId);

HashMap<String, Set<String>> calendarLinksUserMap = dao.getDashboardCalendarContextUserMap();
HashMap<String, Set<String>> newsLinksUserMap = dao.getDashboardNewsContextUserMap();

// combine the context id from keyset of both maps
// so thate we just need to call AuthzGroupService once to find out site members
Set<String> combinedContextIdSet = new HashSet<String>();
combinedContextIdSet.addAll(calendarLinksUserMap.keySet());
combinedContextIdSet.addAll(newsLinksUserMap.keySet());

logger.info(this + ".syncDashboardUsersWithSiteUsers total site set size " + combinedContextIdSet.size());

// now that we have a hashmap, we will check the current site member list
for(String context_id: combinedContextIdSet)
{
HashSet<String> siteUserSet = new HashSet<String>();
Collection<String> siteMembersCollection = getSiteUserIdList(context_id);
if (siteMembersCollection != null)
{
siteUserSet = new HashSet<String>(siteMembersCollection);
}

// remove or add user DashboardCalendarlinks if needed
if (calendarLinksUserMap.containsKey(context_id))
{
addOrRemoveDashboardLinksBasedOnUsersSetComp(context_id, calendarLinksUserMap.get(context_id), siteUserSet, true);
}

// remove or add user DashboardNewslinks if needed
if (newsLinksUserMap.containsKey(context_id))
{
addOrRemoveDashboardLinksBasedOnUsersSetComp(context_id, newsLinksUserMap.get(context_id), siteUserSet, false);
}
}
logger.info(this + ".syncDashboardUsersWithSiteUsers end " + serverId);
}


/**
* Returns the site user id list
*
* @param siteId
* @return Collection of site user ids
*/
private Collection<String> getSiteUserIdList(String siteId)
{
HashSet<String> set = new HashSet<String>();
set.add(sakaiProxy.getSiteReference(siteId));
return this.authzGroupService.getAuthzUsersInGroups(set);
}

/**
* Compare two user sets (one from dashboard calendar/news links table, and the other from site membership)
* add or remove calendar/news links
* @context_id the site id
* @dashboardUserSet
* @siteUserSet
* @forCalendarLinks when true, add/remove in DASH_CALENDAR_LINK table; otherwise, add/remove in DASH_NEWS_LINK table
*/
private void addOrRemoveDashboardLinksBasedOnUsersSetComp(String context_id, Set<String> dashboardUserSet, Set<String> siteUserSet, boolean forCalendarLinks)
{
// construct two base set, one for remove user links, one for add user links
Set<String> removeSet = new HashSet<String>();
removeSet.addAll(dashboardUserSet);
Set<String> addSet = new HashSet<String>();
addSet.addAll(siteUserSet);

// now we have two user sets:
// one is from the current dashboard user record
// the other is from the current site member list
// need to do the comparison between those two sets:
// 1. add dashboard links if the user is added to site;
addSet.removeAll(dashboardUserSet);
for(String userId: addSet)
{
if (forCalendarLinks)
{
addCalendarLinks(userId, context_id);
logger.debug(this + ".syncDashboardUsersWithSiteUsers ADD calendar links for user= " + userId + " context_id=" + context_id);
}
else
{
addNewsLinks(userId, context_id);
logger.debug(this + ".syncDashboardUsersWithSiteUsers ADD news links for user= " + userId + " context_id=" + context_id);
}
}
// 2. remove dashboard links if the user is removed from the site
removeSet.removeAll(siteUserSet);
for(String userId: removeSet)
{
if (forCalendarLinks)
{
removeCalendarLinks(userId, context_id);
logger.debug(this + ".syncDashboardUsersWithSiteUsers REMOVE calendar links for user= " + userId + " context_id=" + context_id);
}
else
{
removeNewsLinks(userId, context_id);
logger.debug(this + ".syncDashboardUsersWithSiteUsers REMOVE news links for user= " + userId + " context_id=" + context_id);
}
}
}
}
Loading

0 comments on commit dbf4b1e

Please sign in to comment.