/**********************************************************************************
* $URL: $
* $Id: $
***********************************************************************************
*
* Author: Charles Hedrick, hedrick@rutgers.edu
*
* Copyright (c) 2010 Rutgers, the State University of New Jersey
*
* 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.lessonbuildertool.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.Role;
import org.sakaiproject.authz.api.RoleAlreadyDefinedException;
import org.sakaiproject.authz.api.SecurityAdvisor;
import org.sakaiproject.authz.cover.AuthzGroupService;
import org.sakaiproject.authz.cover.SecurityService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.InUseException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.lessonbuildertool.SimplePageItem;
import org.sakaiproject.lessonbuildertool.service.LessonEntity;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.db.cover.SqlService;
import org.sakaiproject.db.api.SqlReader;
/**
* Sets up and removes group permissions for assignments and tests. This is to be used so that
* students are not able to access an assignment or test until the Lesson Builder gives them
* permission.
*
* @author Eric Jeney <jeney@rutgers.edu>
*
*/
public class GroupPermissionsService {
private static Log log = LogFactory.getLog(GroupPermissionsService.class);
static private LessonEntity forumEntity = null;
public void setForumEntity(Object e) {
forumEntity = (LessonEntity)e;
}
static private LessonEntity quizEntity = null;
public void setQuizEntity(Object e) {
quizEntity = (LessonEntity)e;
}
static private LessonEntity assignmentEntity = null;
public void setAssignmentEntity(Object e) {
assignmentEntity = (LessonEntity)e;
}
static private LessonEntity bltiEntity = null;
public void setBltiEntity(Object e) {
bltiEntity = (LessonEntity)e;
}
public void init () {
convertGroupsTable();
}
public static String makeGroup(String siteId, String title) throws IOException {
Site site = null;
AuthzGroup realm = null;
try {
site = SiteService.getSite(siteId);
String realmId = SiteService.siteReference(siteId);
realm = AuthzGroupService.getAuthzGroup(realmId);
} catch (Exception e) {
log.warn("Unable to find site " + siteId + ": " + e);
return null;
}
// see if group exists. must be visible
Collection<Group> allGroups = site.getGroups();
for (Group group: allGroups) {
if (title.equals(group.getTitle())) {
if (group.getProperties().getProperty("group_prop_wsetup_created") != null) {
return group.getId();
}
}
}
// need to copy all site roles into new gruop
// in theory they should be the same, but if someone has setup
// non-default roles, then the rule that we copy the user's
// site role into the group will result in trying to access
// a non-existent role.
Set<Role> roles = realm.getRoles();
Group group = site.addGroup();
for (Role role : roles) {
try {
group.addRole(role.getId(), role);
} catch (RoleAlreadyDefinedException e) {
// simpler just to try it and get error
;
}
}
// do we need to check whether title is unique? I'm hopnig not, since we
// will generate only one group per test or assignment
group.setTitle(title);
// needed to get it to show in the UI
group.getProperties().addProperty("group_prop_wsetup_created", Boolean.TRUE.toString());
try {
SiteService.save(site);
} catch (IdUnusedException e) {
log.warn("ID unused", e);
} catch (PermissionException e) {
log.warn("Permission Error", e);
} finally {
// SecurityService.popAdvisor();
}
return group.getId();
}
public static boolean addCurrentUser(String siteId, String userid, String groupId) throws IOException {
try {
// we want to use the same role in the group that the user
// has in the main site.
String realmId = SiteService.siteReference(siteId);
AuthzGroup realm = AuthzGroupService.getAuthzGroup(realmId);
String rolename = realm.getMember(userid).getRole().getId();
groupId = "/site/" + siteId + "/group/" + groupId;
if (AuthzGroupService.getUserRole(userid, groupId) != null) {
// Already in group
return true;
}
SecurityService.pushAdvisor(new SecurityAdvisor() {
public SecurityAdvice isAllowed(String userId, String function, String reference) {
return SecurityAdvice.ALLOWED;
}
});
AuthzGroupService.joinGroup(groupId, rolename, Integer.MAX_VALUE);
} catch (Exception e) {
// Typically means group couldn't be found.
return false;
} finally {
SecurityService.popAdvisor();
}
return true;
}
public static boolean removeUser(String siteId, String userId, String groupId) throws IOException {
groupId = "/site/" + siteId + "/group/" + groupId;
try {
SecurityService.pushAdvisor(new SecurityAdvisor() {
public SecurityAdvice isAllowed(String userId, String function, String reference) {
return SecurityAdvice.ALLOWED;
}
});
AuthzGroupService.unjoinGroup(groupId);
} catch (Exception e) {
// we've got a problem. unjoingroup can fail for maintain users
// we don't want to return false, or the caller will recreate the group.
try {
AuthzGroup group = AuthzGroupService.getAuthzGroup(groupId);
if (group == null)
return false;
if (group.getMember(userId) == null) {
// Already not in group
return true;
}
group.removeMember(userId);
AuthzGroupService.save(group);
return true;
} catch (Exception ee) {
return false;
}
} finally {
SecurityService.popAdvisor();
}
return true;
}
public LessonEntity getEntity(String sakaiId) {
LessonEntity lessonEntity = null;
String prefix = null;
int i = sakaiId.indexOf("/",1);
if (i > 0) {
prefix = sakaiId.substring(1, i);
System.out.println("prefix " + prefix);
if (prefix.equals(LessonEntity.ASSIGNMENT) ||
prefix.equals(LessonEntity.ASSIGNMENT2))
lessonEntity = assignmentEntity.getEntity(sakaiId);
else if (prefix.equals(LessonEntity.SAM_PUB) ||
prefix.equals(LessonEntity.MNEME))
lessonEntity = quizEntity.getEntity(sakaiId);
else if (prefix.equals(LessonEntity.FORUM_TOPIC) ||
prefix.equals(LessonEntity.JFORUM_TOPIC) ||
prefix.equals(LessonEntity.YAFT_TOPIC))
lessonEntity = forumEntity.getEntity(sakaiId);
else if (prefix.equals(LessonEntity.BLTI))
lessonEntity = bltiEntity.getEntity(sakaiId);
else
return null;
} else {
// old format
if (sakaiId.indexOf("-") >= 0)
// id with - in it is assignment
lessonEntity = assignmentEntity.getEntity(sakaiId);
else
// without - it is Samigo
lessonEntity = quizEntity.getEntity(sakaiId);
}
return lessonEntity;
}
// this is a one-time conversion. It seeems silly to add this query to the Dao
// the code is here rather than components to avoid a possible dependency loop. It's not a good idea
// for tool components to refer to each other
void convertGroupsTable() {
// find entries created without siteId
// because this is only needed for old entries, don't need to update the code if we add providers
// for additional tools. This query should be immediate if conversion is done
List <String> sakaiIds = SqlService.dbRead("select itemId from lesson_builder_groups where siteId is null", null, null);
if (sakaiIds == null)
return;
SecurityService.pushAdvisor(new SecurityAdvisor() {
public SecurityAdvice isAllowed(String userId, String function, String reference) {
return SecurityAdvice.ALLOWED;
}
});
try {
for (String sakaiId: sakaiIds) {
String siteId = null;
System.out.println("sakaiid " + sakaiId);
LessonEntity lessonEntity = getEntity(sakaiId);
System.out.println("entity " + lessonEntity);
if (lessonEntity != null) {
siteId = lessonEntity.getSiteId();
System.out.println("siteid " + siteId);
}
if (siteId == null)
siteId = "--";
// if we can't find a siteId set it to -- so we don't keep back trying to handle the entry
Object [] fields = new String[2];
fields[0] = siteId;
fields[1] = sakaiId;
SqlService.dbWrite("update lesson_builder_groups set siteId = ? where itemId = ?", fields);
}
} finally {
SecurityService.popAdvisor();
}
}
}