Search in sources :

Example 1 with MCRRestAPIError

use of org.mycore.restapi.v1.errors.MCRRestAPIError in project mycore by MyCoRe-Org.

the class MCRJSONWebTokenUtil method retrieveAuthenticationToken.

/**
 * returns the access token from Request Header "Authorization"
 * if the token is invalid an MCRRestAPIException is thrown
 *
 * @param request - the HTTPServletRequest object
 * @return the JSON Web Token or null, if not provided in request
 * @throws MCRRestAPIException
 */
public static SignedJWT retrieveAuthenticationToken(HttpServletRequest request) throws MCRRestAPIException {
    String auth = request.getHeader("Authorization");
    if (auth != null && auth.startsWith("Bearer ")) {
        String authToken = auth.substring(7).trim();
        try {
            JWSObject jwsObj = JWSObject.parse(authToken);
            SignedJWT signedJWT = jwsObj.getPayload().toSignedJWT();
            // JWK class does equals only by object id
            if (signedJWT.verify(new RSASSAVerifier((RSAPublicKey) MCRJSONWebTokenUtil.RSA_KEYS.getPublic())) && jwsObj.getHeader().getJWK().toJSONString().equals(JWK.parse(signedJWT.getJWTClaimsSet().getJSONObjectClaim("sub_jwk")).toJSONString())) {
                Date expires = signedJWT.getJWTClaimsSet().getExpirationTime();
                if (Instant.now().isBefore(expires.toInstant())) {
                    return signedJWT;
                } else {
                    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.GERMANY).withZone(ZoneId.systemDefault());
                    throw new MCRRestAPIException(Status.UNAUTHORIZED, new MCRRestAPIError(MCRRestAPIError.CODE_INVALID_AUTHENCATION, "The Authentication Token expired at " + formatter.format(expires.toInstant()), "Please log-in again."));
                }
            } else {
                throw new MCRRestAPIException(Status.UNAUTHORIZED, new MCRRestAPIError(MCRRestAPIError.CODE_INVALID_AUTHENCATION, "The signature of the Authentication Token could not be verified.", null));
            }
        } catch (ParseException | JOSEException e) {
            LOGGER.error(e);
            throw new MCRRestAPIException(Status.UNAUTHORIZED, new MCRRestAPIError(MCRRestAPIError.CODE_INVALID_AUTHENCATION, "Authentication is invalid.", e.getMessage()));
        }
    } else {
        return null;
    }
}
Also used : MCRRestAPIException(org.mycore.restapi.v1.errors.MCRRestAPIException) RSASSAVerifier(com.nimbusds.jose.crypto.RSASSAVerifier) MCRRestAPIError(org.mycore.restapi.v1.errors.MCRRestAPIError) SignedJWT(com.nimbusds.jwt.SignedJWT) ParseException(java.text.ParseException) JWSObject(com.nimbusds.jose.JWSObject) DateTimeFormatter(java.time.format.DateTimeFormatter) JOSEException(com.nimbusds.jose.JOSEException) Date(java.util.Date)

Example 2 with MCRRestAPIError

use of org.mycore.restapi.v1.errors.MCRRestAPIError in project mycore by MyCoRe-Org.

the class MCRRestAPIObjectsHelper method createSortObject.

private static MCRRestAPISortObject createSortObject(String input) throws MCRRestAPIException {
    if (input == null) {
        return null;
    }
    List<MCRRestAPIError> errors = new ArrayList<>();
    MCRRestAPISortObject result = new MCRRestAPISortObject();
    String[] data = input.split(":");
    if (data.length == 2) {
        result.setField(data[0].replace("|", ""));
        String sortOrder = data[1].toLowerCase(Locale.GERMAN).replace("|", "");
        if (!"ID".equals(result.getField()) && !"lastModified".equals(result.getField())) {
            errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_QUERY_PARAMETER, "The sortField is wrong", "Allowed values are 'ID' and 'lastModified'."));
        }
        if ("asc".equals(sortOrder)) {
            result.setOrder(SortOrder.ASC);
        }
        if ("desc".equals(sortOrder)) {
            result.setOrder(SortOrder.DESC);
        }
        if (result.getOrder() == null) {
            errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_QUERY_PARAMETER, "The sortOrder is wrong", "Allowed values for sortOrder are 'asc' and 'desc'."));
        }
    } else {
        errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_QUERY_PARAMETER, "The sort parameter is wrong.", "The syntax should be [sortField]:[sortOrder]."));
    }
    if (errors.size() > 0) {
        throw new MCRRestAPIException(Status.BAD_REQUEST, errors);
    }
    return result;
}
Also used : MCRRestAPIException(org.mycore.restapi.v1.errors.MCRRestAPIException) MCRRestAPIError(org.mycore.restapi.v1.errors.MCRRestAPIError) ArrayList(java.util.ArrayList)

Example 3 with MCRRestAPIError

use of org.mycore.restapi.v1.errors.MCRRestAPIError in project mycore by MyCoRe-Org.

the class MCRRestAPIObjectsHelper method listObjects.

/**
 * returns a list of objects
 * @param info - the injected Jersey URIInfo object
 *
 * @param format - the output format ('xml'|'json')
 * @param filter - a filter criteria
 * @param sort - the sort criteria
 *
 * @return a Jersey response object
 * @throws MCRRestAPIException
 *
 * @see org.mycore.restapi.v1.MCRRestAPIObjects#listObjects(UriInfo, HttpServletRequest, String, String, String)
 */
public static Response listObjects(UriInfo info, HttpServletRequest request, String format, String filter, String sort) throws MCRRestAPIException {
    List<MCRRestAPIError> errors = new ArrayList<>();
    // analyze sort
    MCRRestAPISortObject sortObj = null;
    try {
        sortObj = createSortObject(sort);
    } catch (MCRRestAPIException rae) {
        errors.addAll(rae.getErrors());
    }
    if (format.equals(MCRRestAPIObjects.FORMAT_JSON) || format.equals(MCRRestAPIObjects.FORMAT_XML)) {
    // ok
    } else {
        errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_PARAMETER, "The parameter 'format' is wrong.", "Allowed values for format are 'json' or 'xml'."));
    }
    // analyze filter
    List<String> projectIDs = new ArrayList<>();
    List<String> typeIDs = new ArrayList<>();
    String lastModifiedBefore = null;
    String lastModifiedAfter = null;
    if (filter != null) {
        for (String s : filter.split(";")) {
            if (s.startsWith("project:")) {
                projectIDs.add(s.substring(8));
                continue;
            }
            if (s.startsWith("type:")) {
                typeIDs.add(s.substring(5));
                continue;
            }
            if (s.startsWith("lastModifiedBefore:")) {
                if (!validateDateInput(s.substring(19))) {
                    errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_PARAMETER, "The parameter 'filter' is wrong.", "The value of lastModifiedBefore could not be parsed. Please use UTC syntax: yyyy-MM-dd'T'HH:mm:ss'Z'."));
                    continue;
                }
                if (lastModifiedBefore == null) {
                    lastModifiedBefore = s.substring(19);
                } else if (s.substring(19).compareTo(lastModifiedBefore) < 0) {
                    lastModifiedBefore = s.substring(19);
                }
                continue;
            }
            if (s.startsWith("lastModifiedAfter:")) {
                if (!validateDateInput(s.substring(18))) {
                    errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_PARAMETER, "The parameter 'filter' is wrong.", "The value of lastModifiedAfter could not be parsed. Please use UTC syntax: yyyy-MM-dd'T'HH:mm:ss'Z'."));
                    continue;
                }
                if (lastModifiedAfter == null) {
                    lastModifiedAfter = s.substring(18);
                } else if (s.substring(18).compareTo(lastModifiedAfter) > 0) {
                    lastModifiedAfter = s.substring(18);
                }
                continue;
            }
            errors.add(new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_PARAMETER, "The parameter 'filter' is wrong.", "The syntax of the filter '" + s + "'could not be parsed. The syntax should be [filterName]:[value]. Allowed filterNames are 'project', 'type', 'lastModifiedBefore' and 'lastModifiedAfter'."));
        }
    }
    if (errors.size() > 0) {
        throw new MCRRestAPIException(Status.BAD_REQUEST, errors);
    }
    // Parameters are validated - continue to retrieve data
    // retrieve MCRIDs by Type and Project ID
    Set<String> mcrIDs = new HashSet<>();
    if (projectIDs.isEmpty()) {
        if (typeIDs.isEmpty()) {
            mcrIDs = MCRXMLMetadataManager.instance().listIDs().stream().filter(id -> !id.contains("_derivate_")).collect(Collectors.toSet());
        } else {
            for (String t : typeIDs) {
                mcrIDs.addAll(MCRXMLMetadataManager.instance().listIDsOfType(t));
            }
        }
    } else {
        if (typeIDs.isEmpty()) {
            for (String id : MCRXMLMetadataManager.instance().listIDs()) {
                String[] split = id.split("_");
                if (!split[1].equals("derivate") && projectIDs.contains(split[0])) {
                    mcrIDs.add(id);
                }
            }
        } else {
            for (String p : projectIDs) {
                for (String t : typeIDs) {
                    mcrIDs.addAll(MCRXMLMetadataManager.instance().listIDsForBase(p + "_" + t));
                }
            }
        }
    }
    // Filter by modifiedBefore and modifiedAfter
    List<String> l = new ArrayList<>();
    l.addAll(mcrIDs);
    List<MCRObjectIDDate> objIdDates = new ArrayList<>();
    try {
        objIdDates = MCRXMLMetadataManager.instance().retrieveObjectDates(l);
    } catch (IOException e) {
    // TODO
    }
    if (lastModifiedAfter != null || lastModifiedBefore != null) {
        List<MCRObjectIDDate> testObjIdDates = objIdDates;
        objIdDates = new ArrayList<>();
        for (MCRObjectIDDate oid : testObjIdDates) {
            String test = SDF_UTC.format(oid.getLastModified());
            if (lastModifiedAfter != null && test.compareTo(lastModifiedAfter) < 0)
                continue;
            if (lastModifiedBefore != null && lastModifiedBefore.compareTo(test.substring(0, lastModifiedBefore.length())) < 0)
                continue;
            objIdDates.add(oid);
        }
    }
    // sort if necessary
    if (sortObj != null) {
        objIdDates.sort(new MCRRestAPISortObjectComparator(sortObj));
    }
    String authHeader = MCRJSONWebTokenUtil.createJWTAuthorizationHeader(MCRJSONWebTokenUtil.retrieveAuthenticationToken(request));
    // output as XML
    if (MCRRestAPIObjects.FORMAT_XML.equals(format)) {
        Element eMcrobjects = new Element("mycoreobjects");
        Document docOut = new Document(eMcrobjects);
        eMcrobjects.setAttribute("numFound", Integer.toString(objIdDates.size()));
        for (MCRObjectIDDate oid : objIdDates) {
            Element eMcrObject = new Element("mycoreobject");
            eMcrObject.setAttribute("ID", oid.getId());
            eMcrObject.setAttribute("lastModified", SDF_UTC.format(oid.getLastModified()));
            eMcrObject.setAttribute("href", info.getAbsolutePathBuilder().path(oid.getId()).build().toString());
            eMcrobjects.addContent(eMcrObject);
        }
        try {
            StringWriter sw = new StringWriter();
            XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
            xout.output(docOut, sw);
            return Response.ok(sw.toString()).type("application/xml; charset=UTF-8").header(HEADER_NAME_AUTHORIZATION, authHeader).build();
        } catch (IOException e) {
            throw new MCRRestAPIException(Response.Status.INTERNAL_SERVER_ERROR, new MCRRestAPIError(MCRRestAPIError.CODE_INTERNAL_ERROR, GENERAL_ERROR_MSG, e.getMessage()));
        }
    }
    // output as JSON
    if (MCRRestAPIObjects.FORMAT_JSON.equals(format)) {
        StringWriter sw = new StringWriter();
        try {
            JsonWriter writer = new JsonWriter(sw);
            writer.setIndent("    ");
            writer.beginObject();
            writer.name("numFound").value(objIdDates.size());
            writer.name("mycoreobjects");
            writer.beginArray();
            for (MCRObjectIDDate oid : objIdDates) {
                writer.beginObject();
                writer.name("ID").value(oid.getId());
                writer.name("lastModified").value(SDF_UTC.format(oid.getLastModified()));
                writer.name("href").value(info.getAbsolutePathBuilder().path(oid.getId()).build().toString());
                writer.endObject();
            }
            writer.endArray();
            writer.endObject();
            writer.close();
            return Response.ok(sw.toString()).type("application/json; charset=UTF-8").header(HEADER_NAME_AUTHORIZATION, authHeader).build();
        } catch (IOException e) {
            throw new MCRRestAPIException(Response.Status.INTERNAL_SERVER_ERROR, new MCRRestAPIError(MCRRestAPIError.CODE_INTERNAL_ERROR, GENERAL_ERROR_MSG, e.getMessage()));
        }
    }
    throw new MCRRestAPIException(Response.Status.INTERNAL_SERVER_ERROR, new MCRRestAPIError(MCRRestAPIError.CODE_INTERNAL_ERROR, "A problem in programm flow", null));
}
Also used : XMLOutputter(org.jdom2.output.XMLOutputter) MCRRestAPIException(org.mycore.restapi.v1.errors.MCRRestAPIException) MCRObjectIDDate(org.mycore.datamodel.common.MCRObjectIDDate) Element(org.jdom2.Element) MCRRestAPIError(org.mycore.restapi.v1.errors.MCRRestAPIError) ArrayList(java.util.ArrayList) IOException(java.io.IOException) Document(org.jdom2.Document) JsonWriter(com.google.gson.stream.JsonWriter) StringWriter(java.io.StringWriter) HashSet(java.util.HashSet)

Example 4 with MCRRestAPIError

use of org.mycore.restapi.v1.errors.MCRRestAPIError in project mycore by MyCoRe-Org.

the class MCRRestAPIObjectsHelper method retrieveMCRDerivate.

private static MCRDerivate retrieveMCRDerivate(MCRObject mcrObj, String derIDString) throws MCRRestAPIException {
    // the default value for the key
    String derKey = "mcr";
    if (derIDString.contains(":")) {
        int pos = derIDString.indexOf(":");
        derKey = derIDString.substring(0, pos);
        derIDString = derIDString.substring(pos + 1);
        if (!derKey.equals("mcr") && !derKey.equals("label")) {
            throw new MCRRestAPIException(Response.Status.BAD_REQUEST, new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_ID, "The ID is not valid.", "The prefix is unkown. Only 'mcr' or 'label' are allowed."));
        }
    }
    String matchedDerID = null;
    for (MCRMetaLinkID check : mcrObj.getStructure().getDerivates()) {
        if (derKey.equals("mcr")) {
            if (check.getXLinkHref().equals(derIDString)) {
                matchedDerID = check.getXLinkHref();
                break;
            }
        }
        if (derKey.equals("label")) {
            if (derIDString.equals(check.getXLinkLabel()) || derIDString.equals(check.getXLinkTitle())) {
                matchedDerID = check.getXLinkHref();
                break;
            }
        }
    }
    if (matchedDerID == null) {
        throw new MCRRestAPIException(Response.Status.NOT_FOUND, new MCRRestAPIError(MCRRestAPIError.CODE_NOT_FOUND, "Derivate " + derIDString + " not found.", "The MyCoRe Object with id '" + mcrObj.getId() + "' does not contain a derivate with id '" + derIDString + "'."));
    }
    MCRObjectID derID = MCRObjectID.getInstance(matchedDerID);
    if (!MCRMetadataManager.exists(derID)) {
        throw new MCRRestAPIException(Response.Status.NOT_FOUND, new MCRRestAPIError(MCRRestAPIError.CODE_NOT_FOUND, "There is no derivate with the id '" + matchedDerID + "'.", null));
    }
    return MCRMetadataManager.retrieveMCRDerivate(derID);
}
Also used : MCRRestAPIException(org.mycore.restapi.v1.errors.MCRRestAPIException) MCRRestAPIError(org.mycore.restapi.v1.errors.MCRRestAPIError) MCRMetaLinkID(org.mycore.datamodel.metadata.MCRMetaLinkID) MCRObjectID(org.mycore.datamodel.metadata.MCRObjectID)

Example 5 with MCRRestAPIError

use of org.mycore.restapi.v1.errors.MCRRestAPIError in project mycore by MyCoRe-Org.

the class MCRRestAPIUploadHelper method uploadObject.

/**
 * uploads a MyCoRe Object
 * based upon:
 * http://puspendu.wordpress.com/2012/08/23/restful-webservice-file-upload-with-jersey/
 *
 * @param info - the Jersey UriInfo object
 * @param request - the HTTPServletRequest object
 * @param uploadedInputStream - the inputstream from HTTP Post request
 * @param fileDetails - the file information from HTTP Post request
 * @return a Jersey Response object
 * @throws MCRRestAPIException
 */
public static Response uploadObject(UriInfo info, HttpServletRequest request, InputStream uploadedInputStream, FormDataContentDisposition fileDetails) throws MCRRestAPIException {
    SignedJWT signedJWT = MCRJSONWebTokenUtil.retrieveAuthenticationToken(request);
    java.nio.file.Path fXML = null;
    try (MCRJPATransactionWrapper mtw = new MCRJPATransactionWrapper()) {
        SAXBuilder sb = new SAXBuilder();
        Document docOut = sb.build(uploadedInputStream);
        MCRObjectID mcrID = MCRObjectID.getInstance(docOut.getRootElement().getAttributeValue("ID"));
        if (mcrID.getNumberAsInteger() == 0) {
            mcrID = MCRObjectID.getNextFreeId(mcrID.getBase());
        }
        fXML = UPLOAD_DIR.resolve(mcrID + ".xml");
        docOut.getRootElement().setAttribute("ID", mcrID.toString());
        docOut.getRootElement().setAttribute("label", mcrID.toString());
        XMLOutputter xmlOut = new XMLOutputter(Format.getPrettyFormat());
        try (BufferedWriter bw = Files.newBufferedWriter(fXML, StandardCharsets.UTF_8)) {
            xmlOut.output(docOut, bw);
        }
        MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
        MCRUserInformation currentUser = mcrSession.getUserInformation();
        MCRUserInformation apiUser = MCRUserManager.getUser(MCRJSONWebTokenUtil.retrieveUsernameFromAuthenticationToken(signedJWT));
        mcrSession.setUserInformation(apiUser);
        // handles "create" as well
        MCRObjectCommands.updateFromFile(fXML.toString(), false);
        mcrSession.setUserInformation(currentUser);
        return Response.created(info.getBaseUriBuilder().path("v1/objects/" + mcrID).build()).type("application/xml; charset=UTF-8").header(HEADER_NAME_AUTHORIZATION, MCRJSONWebTokenUtil.createJWTAuthorizationHeader(signedJWT)).build();
    } catch (Exception e) {
        LOGGER.error("Unable to Upload file: {}", String.valueOf(fXML), e);
        throw new MCRRestAPIException(Status.BAD_REQUEST, new MCRRestAPIError(MCRRestAPIError.CODE_WRONG_PARAMETER, "Unable to Upload file: " + String.valueOf(fXML), e.getMessage()));
    } finally {
        if (fXML != null) {
            try {
                Files.delete(fXML);
            } catch (IOException e) {
                LOGGER.error("Unable to delete temporary workflow file: {}", String.valueOf(fXML), e);
            }
        }
    }
}
Also used : XMLOutputter(org.jdom2.output.XMLOutputter) SAXBuilder(org.jdom2.input.SAXBuilder) MCRRestAPIException(org.mycore.restapi.v1.errors.MCRRestAPIException) MCRRestAPIError(org.mycore.restapi.v1.errors.MCRRestAPIError) SignedJWT(com.nimbusds.jwt.SignedJWT) IOException(java.io.IOException) Document(org.jdom2.Document) MCRPersistenceException(org.mycore.common.MCRPersistenceException) MCRRestAPIException(org.mycore.restapi.v1.errors.MCRRestAPIException) MCRAccessException(org.mycore.access.MCRAccessException) IOException(java.io.IOException) BufferedWriter(java.io.BufferedWriter) MCRSession(org.mycore.common.MCRSession) MCRObjectID(org.mycore.datamodel.metadata.MCRObjectID) MCRUserInformation(org.mycore.common.MCRUserInformation)

Aggregations

MCRRestAPIError (org.mycore.restapi.v1.errors.MCRRestAPIError)14 MCRRestAPIException (org.mycore.restapi.v1.errors.MCRRestAPIException)14 IOException (java.io.IOException)10 Document (org.jdom2.Document)7 XMLOutputter (org.jdom2.output.XMLOutputter)6 MCRDerivate (org.mycore.datamodel.metadata.MCRDerivate)6 StringWriter (java.io.StringWriter)5 MCRObjectID (org.mycore.datamodel.metadata.MCRObjectID)5 SignedJWT (com.nimbusds.jwt.SignedJWT)4 Date (java.util.Date)4 Element (org.jdom2.Element)4 MCRUserInformation (org.mycore.common.MCRUserInformation)4 ArrayList (java.util.ArrayList)3 MCRSession (org.mycore.common.MCRSession)3 MCRObjectIDDate (org.mycore.datamodel.common.MCRObjectIDDate)3 MCRObject (org.mycore.datamodel.metadata.MCRObject)3 JsonWriter (com.google.gson.stream.JsonWriter)2 ParseException (java.text.ParseException)2 TreeMap (java.util.TreeMap)2 SolrServerException (org.apache.solr.client.solrj.SolrServerException)2