Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/PrintQbQuestionController.java =================================================================== diff -u -rc47ad82bb2279af8808f519dfc34a4a0d920d258 -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_central/src/java/org/lamsfoundation/lams/web/qb/PrintQbQuestionController.java (.../PrintQbQuestionController.java) (revision c47ad82bb2279af8808f519dfc34a4a0d920d258) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/PrintQbQuestionController.java (.../PrintQbQuestionController.java) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -1,14 +1,21 @@ package org.lamsfoundation.lams.web.qb; +import org.lamsfoundation.lams.qb.model.QbCollection; import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; +import org.lamsfoundation.lams.qb.service.IQbService; +import org.lamsfoundation.lams.security.ISecurityService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.support.RequestContextUtils; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -19,37 +26,60 @@ @Controller @RequestMapping("/qb") public class PrintQbQuestionController { + @Autowired + IQbService qbService; - @GetMapping("/printQuestions.do") + @GetMapping("/printQuestions") public String printQuestions(HttpServletRequest request, Model model) { // read Flash Attributes set by another module and put them in the model Map inputFlashMap = RequestContextUtils.getInputFlashMap(request); if (inputFlashMap != null) { + fillModelWithQuestions(inputFlashMap, model); + } + return "qb/printQuestions"; + } - Map> randomisedOptions = new HashMap<>(); - model.addAttribute("printRandomisedOptions", randomisedOptions); - for (String key : inputFlashMap.keySet()) { - if (key.startsWith("print")) { - model.addAttribute(key, inputFlashMap.get(key)); + @GetMapping("/printQbCollectionQuestions") + public String printQbCollectionQuestions(@RequestParam Long collectionUid, Model model, + HttpServletResponse response) throws IOException { + if (!qbService.hasUserAccessToCollection(collectionUid)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); + return null; + } - if (key.equals("printQuestions")) { - Collection questions = (Collection) inputFlashMap.get(key); - for (QbQuestion question : questions) { - if (question.getType().equals(QbQuestion.TYPE_MATCHING_PAIRS) || question.getType() - .equals(QbQuestion.TYPE_ORDERING)) { - // randomise the order of options when correct answers are hidden - List optionNames = new ArrayList<>(); - for (QbOption option : question.getQbOptions()) { - optionNames.add(option.getName()); - } - Collections.shuffle(optionNames); - randomisedOptions.put(question.getUid(), optionNames); + Map input = new HashMap<>(); + Collection questions = qbService.getCollectionQuestions(collectionUid); + input.put("printQuestions", questions); + QbCollection collection = qbService.getCollectionByUid(collectionUid); + input.put("printTitleSuffix", collection.getName()); + + fillModelWithQuestions(input, model); + return "qb/printQuestions"; + } + + private static void fillModelWithQuestions(Map input, Model model) { + Map> randomisedOptions = new HashMap<>(); + model.addAttribute("printRandomisedOptions", randomisedOptions); + for (String key : input.keySet()) { + if (key.startsWith("print")) { + model.addAttribute(key, input.get(key)); + + if (key.equals("printQuestions")) { + Collection questions = (Collection) input.get(key); + for (QbQuestion question : questions) { + if (question.getType().equals(QbQuestion.TYPE_MATCHING_PAIRS) || question.getType() + .equals(QbQuestion.TYPE_ORDERING)) { + // randomise the order of options when correct answers are hidden + List optionNames = new ArrayList<>(); + for (QbOption option : question.getQbOptions()) { + optionNames.add(option.getName()); } + Collections.shuffle(optionNames); + randomisedOptions.put(question.getUid(), optionNames); } } } } } - return "qb/printQuestions"; } } \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java =================================================================== diff -u -r308be95be92e1e96e2be7e4d041ef7b92fcc7b37 -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java (.../QbCollectionController.java) (revision 308be95be92e1e96e2be7e4d041ef7b92fcc7b37) +++ lams_central/src/java/org/lamsfoundation/lams/web/qb/QbCollectionController.java (.../QbCollectionController.java) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -93,7 +93,7 @@ @RequestMapping("/showOne") public String showOneCollection(@RequestParam long collectionUid, Model model, HttpServletResponse response) throws Exception { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return null; } @@ -112,7 +112,7 @@ @ResponseBody public String getCollectionGridData(@RequestParam long collectionUid, @RequestParam String view, HttpServletRequest request, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return null; } @@ -148,7 +148,7 @@ @ResponseBody public void removeCollectionQuestion(@RequestParam long collectionUid, @RequestParam int qbQuestionId, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return; } @@ -159,7 +159,7 @@ @ResponseBody public String removeCollectionQuestions(@RequestParam long collectionUid, @RequestParam("qbQuestionIds[]") int[] qbQuestionIds, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return null; } @@ -179,7 +179,7 @@ if (!Configuration.getAsBoolean(ConfigurationKeys.QB_COLLECTIONS_TRANSFER_ALLOW)) { throw new SecurityException("Transfering questions between collections is disabled"); } - if (!hasUserAccessToCollection(targetCollectionUid)) { + if (!qbService.hasUserAccessToCollection(targetCollectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return; } @@ -212,7 +212,7 @@ @ResponseBody public String changeCollectionName(@RequestParam(name = "pk") long collectionUid, @RequestParam(name = "value") String name, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return null; } @@ -236,7 +236,7 @@ @RequestMapping(path = "/removeCollection", method = RequestMethod.POST) @ResponseBody public void removeCollection(@RequestParam long collectionUid, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return; } @@ -247,7 +247,7 @@ @ResponseBody public void shareCollection(@RequestParam long collectionUid, @RequestParam int organisationId, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return; } @@ -258,7 +258,7 @@ @ResponseBody public void unshareCollection(@RequestParam long collectionUid, @RequestParam int organisationId, HttpServletResponse response) throws IOException { - if (!hasUserAccessToCollection(collectionUid)) { + if (!qbService.hasUserAccessToCollection(collectionUid)) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "The user does not have access to given collection"); return; } @@ -330,16 +330,4 @@ UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); return user != null ? user.getUserID() : null; } - - private boolean hasUserAccessToCollection(long collectionUid) { - Integer userId = getUserId(); - if (userId == null) { - return false; - } - if (securityService.isAppadmin(userId, "access QB collection", true)) { - return true; - } - Collection collections = qbService.getUserCollections(userId); - return collections.stream().map(QbCollection::getUid).anyMatch(uid -> uid.equals(collectionUid)); - } } \ No newline at end of file Index: lams_central/web/qb/collection.jsp =================================================================== diff -u -r308be95be92e1e96e2be7e4d041ef7b92fcc7b37 -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_central/web/qb/collection.jsp (.../collection.jsp) (revision 308be95be92e1e96e2be7e4d041ef7b92fcc7b37) +++ lams_central/web/qb/collection.jsp (.../collection.jsp) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -3,560 +3,571 @@ - - <fmt:message key="label.qb.collection" /> - - - - - - - - - - - - - - - + .row { + margin-top: 10px; + } + + .middle-cell { + padding-top: 6px; + display: inline-block; + } + + .header-column { + font-weight: bold; + } + + .grid-question-count { + margin-left: 10px; + } + + .grid-collection-private { + color: red !important; + font-size: smaller; + } + + #grid-question-create { + display: inline-block; + float: right; + margin-right: 50px; + } + + #collection-name-row { + min-height: 20px; + margin-top: 20px; + } + + #collection-name:hover+span+i { + visibility:visible + } + #collection-name+span+i { + visibility:hidden + } + + a.thickbox { + color: black; + padding-left: 8px; + } + + select { + height: auto !important; + width: auto !important; + } + + .all-learning-outcomes { + display: none; + } + + .all-learning-outcomes-show { + cursor: pointer; + } + + + + + + + + - - - - - -
- -
- -
- -
+ let questionIdsToRemove = []; + questionsToRemove.forEach(function(questionUid) { + let questionId = $('tr#' + questionUid + ' > td[aria-describedby="collection-grid_id"]', collectionGrid).text(); + if (questionId) { + questionIdsToRemove.push(questionId); + } + }); + + $.ajax({ + 'url' : 'qb/collection/removeCollectionQuestions.do', + 'type' : 'POST', + 'dataType' : 'text', + 'data' : { + 'collectionUid' : ${collection.uid}, + 'qbQuestionIds' : questionIdsToRemove, + "" : "" + }, + 'cache' : false + }).done(function(response){ + if (response == 'fail') { + // not all questions were removed + alert(''); + } + document.location.reload(); + }); + } + + //create proper href for "Create question" button + function initLinkHref() { + var questionType = document.getElementById("question-type").selectedIndex + 1; + $("#create-question-href").attr("href", + "?questionType=" + questionType + + "&oldCollectionUid=${collection.uid}" + + "&KeepThis=true&TB_iframe=true&modal=true"); + }; + + //this method gets invoked after question has been edited and saved + function refreshThickbox(){ + location.reload(); + }; + + function showQuestionsPrintPage() { + let url = ''; + window.open(url, "_blank"); + } + + + + + +
+ +
+ +
+ +
- -   - - - + +   + + + - -
- -
- "> -   - - - <%-- Do not display button for public and private collections --%> - -
- - - -
-
- - - -
- - - - + +
+ + + "> +   - - - - - + + <%-- Do not display button for public and private collections --%> + +
+ + + +
-
- -
- - - - - - - -
- + + + +
+ + + + + + + + + + + +
+ +
+ + + + + + + +
+ -
-   - - - - +
+   + + + + +
+
-
-
- - - - <%-- jqGrid placeholder with some useful attributes --%> -
-
-
-
- -
- -
-
-
- <%-- Do not display links for collection manipulation for public and private collections --%> - + <%-- jqGrid placeholder with some useful attributes --%> +
+
+
+ + +
+ +
+
+ + + <%-- Do not display links for collection manipulation for public and private collections --%> + -
-
- -
-
- - - - <%-- Already shared organisations--%> +
+
+ +
+
+
+ + + <%-- Already shared organisations--%> - - <%-- Not yet shared ones --%> + + <%-- Not yet shared ones --%> - + - -
@@ -629,8 +640,8 @@
@@ -641,17 +652,17 @@
- + + + +
-
- - - - -
- + + + + + + \ No newline at end of file Index: lams_central/web/qb/printQuestions.jsp =================================================================== diff -u -r32a2a44474f2a866af0ce193d299f5ac3554865a -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_central/web/qb/printQuestions.jsp (.../printQuestions.jsp) (revision 32a2a44474f2a866af0ce193d299f5ac3554865a) +++ lams_central/web/qb/printQuestions.jsp (.../printQuestions.jsp) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -14,6 +14,7 @@ body { text-align: center; overflow: visible; + padding-left: 1rem; } #question-list { @@ -51,6 +52,7 @@ body { text-align: left; + padding-left: 0; } .question-item, img { Index: lams_common/src/java/org/lamsfoundation/lams/commonContext.xml =================================================================== diff -u -r52a6369ce66a2ea70d38bfa2e627dfcde6354b10 -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision 52a6369ce66a2ea70d38bfa2e627dfcde6354b10) +++ lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -551,6 +551,7 @@ + Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java =================================================================== diff -u -re7cbf85417c8226f95995e5adb34f7eeb386a98c -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision e7cbf85417c8226f95995e5adb34f7eeb386a98c) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/IQbService.java (.../IQbService.java) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -183,4 +183,6 @@ TreeSet getUnitsFromRequest(HttpServletRequest request, boolean isForSaving); Long allocateVSAnswerToOption(Long qbQuestionUid, Long targetOptionUid, Long previousOptionUid, String answer); + + boolean hasUserAccessToCollection(long collectionUid); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java =================================================================== diff -u -r1e85a36d6397d66fa9cc46b334e2ef2bef8af4f6 -rcb84acde58155494dc2cdf1bae82eac746dadfe2 --- lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision 1e85a36d6397d66fa9cc46b334e2ef2bef8af4f6) +++ lams_common/src/java/org/lamsfoundation/lams/qb/service/QbService.java (.../QbService.java) (revision cb84acde58155494dc2cdf1bae82eac746dadfe2) @@ -49,6 +49,7 @@ import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.qb.model.QbQuestionUnit; import org.lamsfoundation.lams.qb.model.QbToolQuestion; +import org.lamsfoundation.lams.security.ISecurityService; import org.lamsfoundation.lams.tool.ToolContent; import org.lamsfoundation.lams.tool.service.ILamsCoreToolService; import org.lamsfoundation.lams.tool.service.ILamsToolService; @@ -84,9 +85,11 @@ private ILamsToolService toolService; - public static final Comparator COLLECTION_NAME_COMPARATOR = Comparator - .comparing(QbCollection::getName); + private ISecurityService securityService; + public static final Comparator COLLECTION_NAME_COMPARATOR = Comparator.comparing( + QbCollection::getName); + @Override public QbQuestion getQuestionByUid(Long qbQuestionUid) { return qbDAO.getQuestionByUid(qbQuestionUid); @@ -268,8 +271,9 @@ QbStatsActivityDTO activityDTO = new QbStatsActivityDTO(); activityDTO.setActivity(activity); - String monitorUrl = "/lams/" + lamsCoreToolService.getToolMonitoringURL(lessonId, activity) - + "&contentFolderID=" + learningDesign.getContentFolderID(); + String monitorUrl = + "/lams/" + lamsCoreToolService.getToolMonitoringURL(lessonId, activity) + "&contentFolderID=" + + learningDesign.getContentFolderID(); activityDTO.setMonitorURL(monitorUrl); // if there is only 1 participant, there is no point in calculating question indexes @@ -304,8 +308,8 @@ // sort grades by highest mark Collections.sort(userLessonGrades, Comparator.comparing(GradebookUserLesson::getMark).reversed()); // see how many learners should be in top/bottom 27% of the group - int groupCount = (int) Math - .ceil(Configuration.getAsInt(ConfigurationKeys.QB_STATS_GROUP_SIZE) / 100.0 * participantCount); + int groupCount = (int) Math.ceil( + Configuration.getAsInt(ConfigurationKeys.QB_STATS_GROUP_SIZE) / 100.0 * participantCount); // go through each grade and gather data for indexes for (int userIndex = 0; userIndex < participantCount; userIndex++) { @@ -634,12 +638,12 @@ @Override public List getUserCollections(int userId) { Set collections = new LinkedHashSet<>(); - + // even though it is covered by #getUserOwnCollections(), // it creates user private collection when necessary QbCollection privateCollection = getUserPrivateCollection(userId); collections.add(privateCollection); - + collections.addAll(getUserOwnCollections(userId)); QbCollection publicCollection = getPublicCollection(); @@ -689,17 +693,17 @@ } /** - * Is the question in a learning design which is in user's private folder, public folder - * or a course folder where user is a monitor. + * Is the question in a learning design which is in user's private folder, public folder or a course folder where + * user is a monitor. */ @Override public boolean isQuestionInUserMonitoredOrganisationFolder(int qbQuestionId, int userId) { return qbDAO.isQuestionInUserMonitoredOrganisationFolder(qbQuestionId, userId); } /** - * Cascades in QbToolQuestion, QbQuestion and QbOptions do not seem to work on insert. - * New QbQuestions need to be saved step by step. + * Cascades in QbToolQuestion, QbQuestion and QbOptions do not seem to work on insert. New QbQuestions need to be + * saved step by step. */ @Override public void insertQuestion(QbQuestion qbQuestion) { @@ -712,14 +716,14 @@ qbQuestion.setContentFolderId(FileUtil.generateUniqueContentFolderID()); } - Collection qbOptions = qbQuestion.getQbOptions() == null ? null - : new ArrayList<>(qbQuestion.getQbOptions()); + Collection qbOptions = + qbQuestion.getQbOptions() == null ? null : new ArrayList<>(qbQuestion.getQbOptions()); if (qbOptions != null) { qbQuestion.getQbOptions().clear(); } - Collection units = qbQuestion.getUnits() == null ? null - : new ArrayList<>(qbQuestion.getUnits()); + Collection units = + qbQuestion.getUnits() == null ? null : new ArrayList<>(qbQuestion.getUnits()); if (units != null) { qbQuestion.getUnits().clear(); } @@ -833,7 +837,7 @@ * Allocate learner's answer into one of the available answer groups. * * @return if present, it contains optionUid of the option group containing duplicate (added there presumably by - * another teacher working in parallel) + * another teacher working in parallel) */ @Override public Long allocateVSAnswerToOption(Long toolQuestionUid, Long targetOptionUid, Long previousOptionUid, @@ -874,8 +878,9 @@ if (!targetOptionUid.equals(-1L) && targetOption == null) { // front end provided incorrect target option UID - log.error("Target option with UID " + targetOptionUid + " was not found in question with UID " - + qbQuestionUid + " to allocate answer " + answer); + log.error( + "Target option with UID " + targetOptionUid + " was not found in question with UID " + qbQuestionUid + + " to allocate answer " + answer); return null; } @@ -886,7 +891,8 @@ Set nameWithoutUserAnswer = new LinkedHashSet<>(List.of(alternatives)); nameWithoutUserAnswer.remove(answer); - name = nameWithoutUserAnswer.isEmpty() ? "" + name = nameWithoutUserAnswer.isEmpty() + ? "" : nameWithoutUserAnswer.stream().filter(a -> QbUtils.normaliseVSAnswer(a, isExactMatch) != null) .collect(Collectors.joining(QbUtils.VSA_ANSWER_DELIMITER)); previousOption.setName(name); @@ -931,9 +937,9 @@ /** * Extract web form content to QB question. * - * BE CAREFUL: This method will copy necessary info from request form to an old or new AssessmentQuestion - * instance. It gets all info EXCEPT AssessmentQuestion.createDate, which need be set when - * persisting this assessment Question. + * BE CAREFUL: This method will copy necessary info from request form to an old or new AssessmentQuestion instance. + * It gets all info EXCEPT AssessmentQuestion.createDate, which need be set when persisting this assessment + * Question. * * @return qbQuestionModified */ @@ -1008,9 +1014,9 @@ } // set options - if ((type == QbQuestion.TYPE_MULTIPLE_CHOICE) || (type == QbQuestion.TYPE_ORDERING) - || (type == QbQuestion.TYPE_MATCHING_PAIRS) || (type == QbQuestion.TYPE_VERY_SHORT_ANSWERS) - || (type == QbQuestion.TYPE_NUMERICAL) || (type == QbQuestion.TYPE_MARK_HEDGING)) { + if ((type == QbQuestion.TYPE_MULTIPLE_CHOICE) || (type == QbQuestion.TYPE_ORDERING) || (type + == QbQuestion.TYPE_MATCHING_PAIRS) || (type == QbQuestion.TYPE_VERY_SHORT_ANSWERS) || (type + == QbQuestion.TYPE_NUMERICAL) || (type == QbQuestion.TYPE_MARK_HEDGING)) { Set optionList = getOptionsFromRequest(request, true); List options = new ArrayList<>(); int displayOrder = 0; @@ -1055,15 +1061,16 @@ * * @param request * @param isForSaving - * whether the blank options will be preserved or not + * whether the blank options will be preserved or not */ @Override public TreeSet getOptionsFromRequest(HttpServletRequest request, boolean isForSaving) { Map paramMap = splitRequestParameter(request, QbConstants.ATTR_OPTION_LIST); int count = NumberUtils.toInt(paramMap.get(QbConstants.ATTR_OPTION_COUNT)); int questionType = WebUtil.readIntParam(request, QbConstants.ATTR_QUESTION_TYPE); - Integer correctOptionIndex = (paramMap.get(QbConstants.ATTR_OPTION_CORRECT) == null) ? null + Integer correctOptionIndex = (paramMap.get(QbConstants.ATTR_OPTION_CORRECT) == null) + ? null : NumberUtils.toInt(paramMap.get(QbConstants.ATTR_OPTION_CORRECT)); TreeSet optionList = new TreeSet<>(); @@ -1086,8 +1093,8 @@ } option.setDisplayOrder(NumberUtils.toInt(displayOrder)); - if ((questionType == QbQuestion.TYPE_MULTIPLE_CHOICE) - || (questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { + if ((questionType == QbQuestion.TYPE_MULTIPLE_CHOICE) || (questionType + == QbQuestion.TYPE_VERY_SHORT_ANSWERS)) { String name = paramMap.get(QbConstants.ATTR_OPTION_NAME_PREFIX + i); if (name == null && isForSaving && !(questionType == QbQuestion.TYPE_VERY_SHORT_ANSWERS && i < 2)) { continue; @@ -1204,6 +1211,19 @@ return unitList; } + @Override + public boolean hasUserAccessToCollection(long collectionUid) { + Integer userId = getUserId(); + if (userId == null) { + return false; + } + if (securityService.isAppadmin(userId, "access QB collection", true)) { + return true; + } + Collection collections = getUserCollections(userId); + return collections.stream().map(QbCollection::getUid).anyMatch(uid -> uid.equals(collectionUid)); + } + private Map splitRequestParameter(HttpServletRequest request, String parameterName) { String list = request.getParameter(parameterName); if (list == null) { @@ -1256,4 +1276,8 @@ public void setToolService(ILamsToolService toolService) { this.toolService = toolService; } + + public void setSecurityService(ISecurityService securityService) { + this.securityService = securityService; + } } \ No newline at end of file