Skip to content

Commit

Permalink
SAK-41172 Group Locking Enhancements (sakaiproject#6536)
Browse files Browse the repository at this point in the history
* SAK-41172 Group Locking Enhancements

* Fixup spacing
  • Loading branch information
ern authored Nov 4, 2019
1 parent c17058a commit 0b9d28b
Show file tree
Hide file tree
Showing 43 changed files with 929 additions and 548 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzPermissionException;
import org.sakaiproject.authz.api.AuthzRealmLockException;
import org.sakaiproject.authz.api.GroupAlreadyDefinedException;
import org.sakaiproject.authz.api.GroupIdInvalidException;
import org.sakaiproject.authz.api.GroupNotDefinedException;
Expand Down Expand Up @@ -626,6 +627,10 @@ public void doSave(RunData data)
{
addAlert(state, rb.getFormattedMessage("alert_permission", new Object[]{edit.getReference()}));
}
catch (AuthzRealmLockException arle)
{
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}
}

// clean up state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzGroupService;
import org.sakaiproject.authz.api.AuthzPermissionException;
import org.sakaiproject.authz.api.AuthzRealmLockException;
import org.sakaiproject.authz.api.FunctionManager;
import org.sakaiproject.authz.api.GroupAlreadyDefinedException;
import org.sakaiproject.authz.api.GroupIdInvalidException;
Expand Down Expand Up @@ -792,6 +793,10 @@ public void doCancel(RunData data, Context context)
{
addAlert(state, rb.getFormattedMessage("realm.notpermis2", new Object[]{realm.getId()}));
}
catch (AuthzRealmLockException arle)
{
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}
}
}

Expand Down Expand Up @@ -848,6 +853,10 @@ public void doRemove_confirmed(RunData data, Context context)
{
addAlert(state, rb.getFormattedMessage("realm.notpermis2", new Object[]{realm.getId()}));
}
catch (AuthzRealmLockException arle)
{
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}

// cleanup
cleanState(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.sakaiproject.alias.api.AliasService;
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzGroupService;
import org.sakaiproject.authz.api.AuthzRealmLockException;
import org.sakaiproject.authz.api.GroupNotDefinedException;
import org.sakaiproject.authz.api.Role;
import org.sakaiproject.authz.api.SecurityService;
Expand Down Expand Up @@ -1865,8 +1866,8 @@ public void doCancel_group(RunData data, Context context)
{
try {
site.deleteGroup(group);
} catch (IllegalStateException e) {
log.error(".doCancel_group: Group with id {} cannot be removed because is locked", group.getId());
} catch (AuthzRealmLockException arle) {
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}
}

Expand All @@ -1893,8 +1894,8 @@ public void doRemove_group(RunData data, Context context)
// remove the page (no confirm)
try {
site.deleteGroup(group);
} catch (IllegalStateException e) {
log.error(".doRemove_group: Group with id {} cannot be removed because is locked", group.getId());
} catch (AuthzRealmLockException arle) {
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}

// done with the page
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzGroupService;
import org.sakaiproject.authz.api.AuthzPermissionException;
import org.sakaiproject.authz.api.AuthzRealmLockException;
import org.sakaiproject.authz.api.FunctionManager;
import org.sakaiproject.authz.api.GroupNotDefinedException;
import org.sakaiproject.authz.api.Member;
Expand Down Expand Up @@ -908,6 +909,8 @@ public void deleteAssignment(Assignment assignment) throws PermissionException {
log.debug("successful delete for assignment with id = {}", assignment.getId());
} catch (AuthzPermissionException e) {
log.warn("deleting realm for assignment reference = {}", reference, e);
} catch (AuthzRealmLockException arle) {
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}
}

Expand Down Expand Up @@ -1161,6 +1164,8 @@ public void removeSubmission(AssignmentSubmission submission) throws PermissionE
log.warn("removing realm for : {} : {}", reference, e.getMessage());
} catch (GroupNotDefinedException e) {
log.warn("cannot find group for submission : {} : {}", reference, e.getMessage());
} catch (AuthzRealmLockException arle) {
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import org.sakaiproject.assignment.taggable.tool.DecoratedTaggingProvider.Pager;
import org.sakaiproject.assignment.taggable.tool.DecoratedTaggingProvider.Sort;
import org.sakaiproject.authz.api.*;
import org.sakaiproject.authz.api.AuthzGroup.RealmLockMode;
import org.sakaiproject.calendar.api.Calendar;
import org.sakaiproject.calendar.api.CalendarEvent;
import org.sakaiproject.calendar.api.CalendarEventEdit;
Expand Down Expand Up @@ -1867,7 +1868,7 @@ private String build_student_view_submission_confirmation_context(VelocityPortle

if (currentAssignment.getIsGroup()) {
context.put("submitterNames", getSubmitterFormattedNames(s, "build_student_view_submission_confirmation_context"));

}
}
}
Expand Down Expand Up @@ -7936,7 +7937,7 @@ private void post_save_assignment(RunData data, String postOrSave) {
rubricsService.saveRubricAssociation(RubricsConstants.RBCS_TOOL_ASSIGNMENT, a.getId(), getRubricConfigurationParameters(params));

// Locking and unlocking groups
rangeAndGroups.postSaveAssignmentGroupLocking(state, post, rangeAndGroupSettings, aOldGroups, siteId, a.getId());
rangeAndGroups.postSaveAssignmentGroupLocking(state, post, rangeAndGroupSettings, aOldGroups, siteId, assignmentReference);

if (post) {
// we need to update the submission
Expand Down Expand Up @@ -9701,7 +9702,7 @@ public void doDelete_assignment(RunData data) {
for (String reference : groups) {
Group group = site.getGroup(reference);
if (group != null) {
group.unlockGroup(group.getReference() + "/assignment/" + assignment.getId(), Group.LockMode.ALL);
group.setLockForReference(ref, RealmLockMode.NONE);
siteService.save(group.getContainingSite());
}
}
Expand Down Expand Up @@ -10500,7 +10501,7 @@ public void doAttachments(RunData data) {
} else if (MODE_STUDENT_REVIEW_EDIT.equals(mode)) {
saveReviewGradeForm(data, state, "save");
}

//Set the title and override for anonymous assignment
if (assignment != null) {
assignmentTitle = assignment.getTitle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.sakaiproject.assignment.api.AssignmentService;
import org.sakaiproject.assignment.api.MultiGroupRecord;
import org.sakaiproject.assignment.api.model.Assignment;
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.cheftool.Context;
import org.sakaiproject.cheftool.RunData;
Expand Down Expand Up @@ -47,11 +48,11 @@ class RangeAndGroupsDelegate
private static final String VALUE_ASSIGN_TO_INDIVIDUALS_FROM_GROUPS = "individualsFromGroups";
private static final String VALUE_ASSIGN_TO_GROUPS = "groups";

private final AssignmentService asnServ;
private final AssignmentService assignmentService;
private final ResourceLoader rb;
private final SiteService siteServ;
private final SecurityService secServ;
private final FormattedText fmtTxt;
private final SiteService siteService;
private final SecurityService securityService;
private final FormattedText formattedText;

void buildInstructorNewEditAssignmentContextGroupCheck(Context context, Assignment asn)
{
Expand All @@ -63,17 +64,17 @@ void buildInstructorNewEditAssignmentContextGroupCheck(Context context, Assignme
List<MultiGroupRecord> dupes = defaultMultipleGroupCheck(asn);
if (!dupes.isEmpty())
{
context.put("multipleGroupUsers", fmtTxt.escapeHtml(formatDuplicateMemberships(dupes)));
context.put("multipleGroupUsers", formattedText.escapeHtml(formatDuplicateMemberships(dupes)));
}
}

void setAssignmentFormContext(SessionState state, Context context, String contextString, AssignmentAction asnAct)
{
String range = StringUtils.trimToNull((String) state.getAttribute(NEW_ASSIGNMENT_RANGE));
Collection<Group> groupsAllowAddAssignment = asnServ.getGroupsAllowAddAssignment(contextString);
Collection<Group> groupsAllowAddAssignment = assignmentService.getGroupsAllowAddAssignment(contextString);
if (range == null)
{
if (asnServ.allowAddSiteAssignment(contextString))
if (assignmentService.allowAddSiteAssignment(contextString))
{
range = Assignment.Access.SITE.toString();
}
Expand Down Expand Up @@ -145,7 +146,7 @@ else if (VALUE_ASSIGN_TO_INDIVIDUALS_FROM_GROUPS.equals(assignTo))
if (groupAssignment)
{
List<String> groupIds = Arrays.asList(data.getParameters().getStrings("selectedGroups"));
List<MultiGroupRecord> dupes = asnServ.checkAssignmentForUsersInMultipleGroups(siteId, groupsFromIds(siteId, groupIds));
List<MultiGroupRecord> dupes = assignmentService.checkAssignmentForUsersInMultipleGroups(siteId, groupsFromIds(siteId, groupIds));
alertDuplicateMemberships(dupes, state);
}

Expand Down Expand Up @@ -193,37 +194,38 @@ else if (groupChoice != null)
return new RangeAndGroupSettings(isGroupSubmit, range, groups);
}

void postSaveAssignmentGroupLocking(SessionState state, boolean post, RangeAndGroupSettings settings, Collection<String> aOldGroups, String siteId, String asnId)
void postSaveAssignmentGroupLocking(SessionState state, boolean post, RangeAndGroupSettings settings, Collection<String> aOldGroups, String siteId, String assignmentReference)
{
List<String> lockedGroupsReferences = new ArrayList<>();
if (post && settings.isGroupSubmit && !settings.groups.isEmpty())
{
for (Group group : settings.groups)
{
String groupAssignmentReference = group.getReference() + "/assignment/" + asnId;

log.debug("Getting groups from reference: {}", groupAssignmentReference);
// Prior to SAK-41172 the string concatenation:
// 'group.getReference() + "/assignment/" + a.getId()'
// was used to create the reference for a lock
// this was simplified to the assignment reference
lockedGroupsReferences.add(group.getReference());
log.debug("Adding group: {}", group.getReference());
log.debug("Adding group to lock list: {}", group.getReference());

if (!aOldGroups.contains(group.getReference()) || !group.isLocked(groupAssignmentReference, Group.LockMode.ALL))
if (!aOldGroups.contains(group.getReference()) || group.getLockForReference(assignmentReference) == AuthzGroup.RealmLockMode.NONE)
{
log.debug("locking group: {}", group.getReference());
group.lockGroup(groupAssignmentReference, Group.LockMode.ALL);
group.setLockForReference(assignmentReference, AuthzGroup.RealmLockMode.ALL);
log.debug("locked group: {}", group.getReference());

try
{
siteServ.save(group.getContainingSite());
siteService.save(group.getContainingSite());
}
catch (IdUnusedException e)
{
log.warn(".post_save_assignment: Cannot find site with id {}", siteId);
log.warn("Cannot find site with id {}", siteId);
VelocityPortletPaneledAction.addAlert(state, rb.getFormattedMessage("options_cannotFindSite", siteId));
}
catch (PermissionException e)
{
log.warn(".post_save_assignment: Do not have permission to edit site with id {}", siteId);
log.warn("Do not have permission to edit site with id {}", siteId);
VelocityPortletPaneledAction.addAlert(state, rb.getFormattedMessage("options_cannotEditSite", siteId));
}
}
Expand All @@ -234,7 +236,7 @@ void postSaveAssignmentGroupLocking(SessionState state, boolean post, RangeAndGr
{
try
{
Site site = siteServ.getSite(siteId);
Site site = siteService.getSite(siteId);

for (String reference : aOldGroups)
{
Expand All @@ -244,9 +246,8 @@ void postSaveAssignmentGroupLocking(SessionState state, boolean post, RangeAndGr
Group group = site.getGroup(reference);
if (group != null)
{
String groupReferenceAssignment = group.getReference() + "/assignment/" + asnId;
group.unlockGroup(groupReferenceAssignment, Group.LockMode.ALL);
siteServ.save(group.getContainingSite());
group.setLockForReference(assignmentReference, AuthzGroup.RealmLockMode.NONE);
siteService.save(group.getContainingSite());
}
}
}
Expand Down Expand Up @@ -289,7 +290,7 @@ void initializeAssignment(SessionState state)
*/
List<MultiGroupRecord> defaultMultipleGroupCheck(Assignment asn)
{
return asnServ.checkAssignmentForUsersInMultipleGroups(asn.getContext(), groupsFromRefs(asn.getContext(), asn.getGroups()));
return assignmentService.checkAssignmentForUsersInMultipleGroups(asn.getContext(), groupsFromRefs(asn.getContext(), asn.getGroups()));
}

/**
Expand Down Expand Up @@ -318,13 +319,13 @@ Collection<MultiGroupRecord> checkAssignmentForUsersInMultipleGroups(Assignment
*/
Collection<MultiGroupRecord> checkSubmissionForUsersInMultipleGroups(Assignment asn, Group submissionGroup, SessionState state, boolean showAlert)
{
if (submissionGroup == null || secServ.isSuperUser()) // don't check this for admin users / short circuit if no group given
if (submissionGroup == null || securityService.isSuperUser()) // don't check this for admin users / short circuit if no group given
{
return Collections.emptyList();
}

String siteId = asn.getContext();
List<MultiGroupRecord> dupes = asnServ.checkSubmissionForUsersInMultipleGroups(siteId, submissionGroup, groupsFromRefs(siteId, asn.getGroups()));
List<MultiGroupRecord> dupes = assignmentService.checkSubmissionForUsersInMultipleGroups(siteId, submissionGroup, groupsFromRefs(siteId, asn.getGroups()));
if (showAlert)
{
alertDuplicateNames(dupes, state);
Expand Down Expand Up @@ -367,7 +368,7 @@ void buildStudentViewAssignmentContext(SessionState state, String userId, Assign

void buildInstructorGradeAssignmentContext(SessionState state, Context context, Assignment asn)
{
Collection<String> dupes = checkAssignmentForUsersInMultipleGroups(asn, state).stream().map(mgr -> fmtTxt.escapeHtml(mgr.user.getDisplayName())).collect(Collectors.toList());
Collection<String> dupes = checkAssignmentForUsersInMultipleGroups(asn, state).stream().map(mgr -> formattedText.escapeHtml(mgr.user.getDisplayName())).collect(Collectors.toList());
if (!dupes.isEmpty())
{
context.put("usersinmultiplegroups", dupes);
Expand Down Expand Up @@ -395,7 +396,7 @@ boolean validateUserGroups(SessionState state, String userId, Assignment asn)
}

// user is not in any assignment groups, if they are an instructor this is probably the Student View feature so let them through
return asnServ.allowAddAssignment(site.getId()) || asnServ.allowUpdateAssignmentInContext(site.getId());
return assignmentService.allowAddAssignment(site.getId()) || assignmentService.allowUpdateAssignmentInContext(site.getId());
}

void buildInstructorGradeSubmissionContextGroupCheck(Optional<Assignment> asnOpt, String groupId, SessionState state)
Expand All @@ -419,7 +420,7 @@ private Site getSite(Assignment asn)
{
try
{
return siteServ.getSite(asn.getContext());
return siteService.getSite(asn.getContext());
}
catch (IdUnusedException e)
{
Expand All @@ -433,7 +434,7 @@ private void alertDuplicates(String msg, SessionState state)
if (!msg.isEmpty())
{
String baseMessage = rb.getString("group.user.multiple.warning");
VelocityPortletPaneledAction.addAlert(state, fmtTxt.escapeHtml(baseMessage + " " + msg));
VelocityPortletPaneledAction.addAlert(state, formattedText.escapeHtml(baseMessage + " " + msg));
}
}

Expand Down Expand Up @@ -478,7 +479,7 @@ private List<Group> groupsFromIdsOrRefs(String siteId, Collection<String> groups
{
try
{
return siteServ.getSite(siteId).getGroups().stream().filter(g -> groups.contains(accessor.apply(g))).collect(Collectors.toList());
return siteService.getSite(siteId).getGroups().stream().filter(g -> groups.contains(accessor.apply(g))).collect(Collectors.toList());
}
catch (IdUnusedException e)
{
Expand All @@ -497,7 +498,7 @@ private List<Group> groupsFromIdsOrRefs(String siteId, Collection<String> groups
*/
private List<Group> getGroupsWithUser(String userId, Assignment asn, Site site)
{
boolean isAdmin = secServ.isSuperUser();
boolean isAdmin = securityService.isSuperUser();
return asn.getGroups().stream().map(gref -> site.getGroup(gref)).filter(Objects::nonNull)
.filter(g -> g.getMember(userId) != null || isAdmin) // allow admin to submit on behalf of groups
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -888,8 +888,13 @@ public void removeCalendar(CalendarEdit calendar) throws PermissionException
{
log.warn("removeCalendar: removing realm for : " + calendar.getReference() + " : " + e);
}
catch (GroupNotDefinedException ignore)
catch (GroupNotDefinedException gnde)
{
log.debug(gnde.getMessage());
}
catch (AuthzRealmLockException arle)
{
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}

} // removeCalendar
Expand Down Expand Up @@ -2917,8 +2922,13 @@ public void removeEvent(CalendarEventEdit edit, int intention) throws Permission
{
log.warn("removeEvent: removing realm for : " + edit.getReference() + " : " + e);
}
catch (GroupNotDefinedException ignore)
catch (GroupNotDefinedException gnde)
{
log.debug(gnde.getMessage());
}
catch (AuthzRealmLockException arle)
{
log.warn("GROUP LOCK REGRESSION: {}", arle.getMessage(), arle);
}

} // removeEvent
Expand Down
Loading

0 comments on commit 0b9d28b

Please sign in to comment.