Ignore:
Timestamp:
2017-03-24T21:37:12+13:00 (7 years ago)
Author:
ak19
Message:

First commit for getting user comments working for GS3. It all works, but there's debugging statements still and haven't cleaned up commented out code. After that, would like to make POST rather than GET AJAX calls, so more refactoring required. 1. config_format.xsl is just minor spelling corrections. 2. header.xsl has a new function generateLogoutURL. 3. document.xsl imports and calls new usercomments.xsl to set up the user comments area. 4. New usercomments.js is imported by new usercomments.xsl, and sets up the interaction of the usercomments area. 5. javascript-global-functions.js now contains setMetadataArray and getMetadataArray functions to parallel what GS2 used in gsajaxapi.js, but for GS3 need to go through GS2Construct.processModifyMetadata() service in java code. 5. GS2Construct.java does different checking for users adding user comments versus users doing document editing. For the latter, the user needs to have editing permissions for the document. But any user is allowed to add comments on any accessible document. But ModifyMetadata should not allow any other metadata to be modified other than meta fields. 6. New language strings for usercomment area and GS2Construct errors in the 2 changed properties files.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Construct.java

    r31127 r31537  
    2929import java.util.Map;
    3030import java.util.Set;
     31import java.util.regex.Matcher;
     32import java.util.regex.Pattern;
    3133
    3234import org.apache.log4j.Logger;
     
    4244import org.greenstone.gsdl3.util.UserContext;
    4345import org.greenstone.gsdl3.util.XMLConverter;
     46
     47// https://developer.android.com/reference/org/json/JSONObject.html
     48// https://developer.android.com/reference/org/json/JSONArray.html
     49import org.json.JSONArray;
     50import org.json.JSONException;
     51import org.json.JSONObject;
     52
    4453
    4554import org.w3c.dom.Document;
     
    311320    protected Element processModifyMetadata(Element request)
    312321    {
    313         if (!userHasCollectionEditPermissions(request)) {
     322
     323        // There are two types of operations whereby metadata gets modified:
     324        // - document including document-meta editing: user needs document editing powers
     325        // - adding user comments: user just needs an account and needs to be logged in
     326        // We handle both cases in this service.
     327
     328        Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
     329        HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
     330
     331        // If a user is only adding comments, they don't need to have editing powers over a collection
     332        // but they need to be logged in
     333        String[] docids = isAddingUserComments(request, params);
     334        boolean isAddingUserComments = (docids == null) ? false : true;
     335
     336        if(isAddingUserComments) { // adding user comments, check if user logged in
     337        UserContext context = new UserContext(request);
     338
     339        // A restricted set of metadata is modifiable when adding user comments:
     340        // only the username, usertimestamp and usercomment metadata fields.
     341        // If that's all that's being modified, isAddingUserComments() would have returned true,
     342        // so finally check if the caller is logged in as a user.
     343        if (context.getUsername().equals("")) {
     344            Document result_doc = XMLConverter.newDOM();
     345            Element result = GSXML.createBasicResponse(result_doc, "processModifyMetadata");
     346            GSXML.addError(result, "Cannot add user comments if not logged in."); // or if attempting to set meta not related to user comments.
     347            return result; // not logged in
     348        }
     349
     350        }
     351        else if (!userHasCollectionEditPermissions(request, params)) {
    314352        Document result_doc = XMLConverter.newDOM();
    315353        Element result = GSXML.createBasicResponse(result_doc, "processModifyMetadata");
    316         GSXML.addError(result, "This user does not have the required permissions to perform this action.");
     354        GSXML.addError(result, "This user does not have the required permissions to perform this action."); // also get here if user was attempting to set meta not related to user comments.
    317355        return result;
    318356        }
     
    323361       
    324362        // process
    325         Element response = runCommand(request, GS2PerlConstructor.MODIFY_METADATA_SERVER);
     363        Element response = runCommand(request, GS2PerlConstructor.MODIFY_METADATA_SERVER, docids);
    326364       
    327365        if (response.getElementsByTagName(GSXML.ERROR_ELEM).getLength() <= 0) // if no errors, wait for process to finish
     
    666704    }
    667705
     706    protected Element runCommand(Element request, int type) {
     707        return runCommand(request, type, null);
     708    }
     709
    668710    /** returns a response element */
    669     protected Element runCommand(Element request, int type)
    670     {
    671       Document result_doc = XMLConverter.newDOM();
     711    protected Element runCommand(Element request, int type, String[] docids)
     712    {
     713        Document result_doc = XMLConverter.newDOM();
    672714        // the response to send back
    673715        String name = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
     
    757799           
    758800            String oid = null;
    759            
     801
    760802            while (i.hasNext()) {
    761803
    762804                Map.Entry<String, Serializable> entry = i.next();
    763805                String paramname = entry.getKey();
    764                 paramname = paramname.replace("s1.", ""); // replaces all
    765                                                             // occurrences
     806                paramname = paramname.replace("s1.", ""); // replaces all occurrences
    766807                if (paramname.equals("collection")) {
    767808                    paramname = "c";
     
    770811                    oid = (String) entry.getValue();
    771812                }
     813               
    772814                String paramvalue = (String) entry.getValue();
    773815
     
    778820            }
    779821           
    780             markDocumentInFlatDatabase("R", coll_name, OID.getTop(oid));
     822            if(oid != null) { // if we have only one oid
     823            markDocumentInFlatDatabase("R", coll_name, OID.getTop(oid));
     824            } else if (docids != null) { // check if we are dealing with many doc ids, as cold in theory happen when set-metadata-array is called
     825           
     826            for(int index = 0; index < docids.length; index++) {
     827                String docid = docids[index];
     828                markDocumentInFlatDatabase("R", coll_name, OID.getTop(docid));
     829            }
     830            } else {
     831            String msg = getTextString("general.no_valid_docid_error", lang);
     832            logger.error("*** " + msg);
     833            Text t = result_doc.createTextNode(msg);
     834            status.appendChild(t);
     835            status.setAttribute(GSXML.STATUS_ERROR_CODE_ATT, Integer.toString(GSStatus.ERROR));
     836            return response;
     837            }
    781838           
    782839            constructor.setQueryString(querystring.toString());
     
    9651022
    9661023
     1024    protected String[] isAddingUserComments(Element request, HashMap<String, Serializable> params) {
     1025
     1026    String metaserver_command = (String) params.get("a"); // e.g. set-archives-metadata or set-metadata-array
     1027    // quickest test:
     1028    // if not calling set-metadata-array, then it definitely won't be a set-usercomments operation
     1029    if(!metaserver_command.equals("set-metadata-array")) {
     1030        return null;
     1031    }
     1032
     1033    // Confirm that the set-meta-array operation is only attempting to modify user comments metadata
     1034
     1035    String[] docids = null;
     1036    String json_str = (String) params.get("json"); // will have a "json" field if doing set-meta-array
     1037    Pattern p = Pattern.compile("^(username|usertimestamp|usercomment)$");
     1038
     1039    // check that the name of each that's metadata to be set is one of username|usercomment|usertimestamp
     1040    // Anything else means something more than adding user comments is being attempted, which is invalid
     1041    try {
     1042       
     1043        JSONArray docInfoList = new JSONArray(json_str);
     1044        docids = new String[docInfoList.length()];
     1045        for(int index = 0; index < docInfoList.length(); index++) {
     1046        JSONObject docInfo = docInfoList.getJSONObject(index);
     1047        if(docInfo.has("metatable")) { // should exist for metadata arrays
     1048           
     1049            docids[index] = docInfo.getString("docid"); // should exist if metatable existed
     1050
     1051            logger.info("@@@ Found docid: " + docids[index]);
     1052
     1053            JSONArray metatable = docInfo.getJSONArray("metatable");
     1054            for(int i = 0; i < metatable.length(); i++) {
     1055            JSONObject meta = metatable.getJSONObject(i);
     1056
     1057            String metaname = meta.getString("metaname");
     1058            logger.info("### metaname: " + metaname);
     1059            Matcher m = p.matcher(metaname);
     1060            if(!m.matches()) {
     1061                logger.info("### metaname: " + metaname + " doesn't match");
     1062                return null;
     1063            }
     1064            }
     1065        }
     1066        }
     1067    } catch(JSONException jsonex) {
     1068        logger.error("Exception when parsing json string: " + json_str);
     1069        logger.error(jsonex);
     1070       
     1071    }
     1072   
     1073    // if we're here, then it means that the JSON only asked for username|usercomment|usertimestamp meta
     1074    // meaning that the setmeta operation was a valid user comment operation.
     1075    // In that case, we have a docid for which we need to add a user comment
     1076    // set-metadata-array can take more docids, but doesn't happen for a user comment. And one comment
     1077    // is added at a time, but 3 meta fields are set for each comment: username, usercomment and timestamp
     1078    // hence the use of set-meta-array.
     1079    return docids;
     1080
     1081    }
     1082
    9671083    /** Copy from DebugService.userHasEditPermissions
    9681084     This function checks that the user is logged in and that the user
     
    9711087    Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
    9721088    HashMap<String, Serializable> params = GSXML.extractParams(param_list, false);
     1089
     1090    return userHasCollectionEditPermissions(request, params);
     1091
     1092    }
     1093
     1094    protected boolean userHasCollectionEditPermissions(Element request, HashMap<String, Serializable> params) {
    9731095    String collection = (String) params.get(COL_PARAM); // could be null on newcoll operation
     1096
    9741097
    9751098    UserContext context = new UserContext(request);
     
    9771100    return !context.getUsername().equals("");
    9781101    }
     1102
     1103    // START DEBUG
     1104    Set<Map.Entry<String, Serializable>> entries = params.entrySet();
     1105    Iterator<Map.Entry<String, Serializable>> i = entries.iterator();
     1106   
     1107    StringBuffer parametersLine = new StringBuffer();
     1108    while (i.hasNext()) {
     1109   
     1110    Map.Entry<String, Serializable> entry = i.next();
     1111    String paramname = entry.getKey();
     1112    String paramvalue = (String) entry.getValue();
     1113   
     1114    parametersLine.append("\t" + paramname + ": " + paramvalue + "\n");
     1115    }
     1116   
     1117    logger.info("XXXXXXXXXXXXX PARAMETERS:\n" + parametersLine);
     1118    // END DEBUG
     1119
    9791120    for (String group : context.getGroups()) {
    9801121      // administrator always has permission
Note: See TracChangeset for help on using the changeset viewer.