Search in sources :

Example 1 with Authenticator

use of org.structr.core.auth.Authenticator in project structr by structr.

the class CsvServlet method doGet.

@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws UnsupportedEncodingException {
    Authenticator authenticator = null;
    Result result = null;
    Resource resource = null;
    try {
        // isolate request authentication in a transaction
        try (final Tx tx = StructrApp.getInstance().tx()) {
            authenticator = config.getAuthenticator();
            securityContext = authenticator.initializeAndExamineRequest(request, response);
            tx.success();
        }
        final App app = StructrApp.getInstance(securityContext);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/csv; charset=utf-8");
        // set default value for property view
        propertyView.set(securityContext, defaultPropertyView);
        // evaluate constraints and measure query time
        double queryTimeStart = System.nanoTime();
        // isolate resource authentication
        try (final Tx tx = app.tx()) {
            resource = ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView);
            authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
            tx.success();
        }
        try (final Tx tx = app.tx()) {
            String resourceSignature = resource.getResourceSignature();
            // let authenticator examine request again
            authenticator.checkResourceAccess(securityContext, request, resourceSignature, propertyView.get(securityContext));
            // add sorting & paging
            String pageSizeParameter = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_SIZE);
            String pageParameter = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_NUMBER);
            String sortOrder = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_ORDER);
            String sortKeyName = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_KEY);
            boolean sortDescending = (sortOrder != null && "desc".equals(sortOrder.toLowerCase()));
            int pageSize = Services.parseInt(pageSizeParameter, NodeFactory.DEFAULT_PAGE_SIZE);
            int page = Services.parseInt(pageParameter, NodeFactory.DEFAULT_PAGE);
            PropertyKey sortKey = null;
            // set sort key
            if (sortKeyName != null) {
                Class<? extends GraphObject> type = resource.getEntityClass();
                sortKey = StructrApp.getConfiguration().getPropertyKeyForDatabaseName(type, sortKeyName, false);
            }
            // Should line breaks be removed?
            removeLineBreaks = StringUtils.equals(request.getParameter(REMOVE_LINE_BREAK_PARAM), "1");
            // Should a leading BOM be written?
            writeBom = StringUtils.equals(request.getParameter(WRITE_BOM), "1");
            // do action
            result = resource.doGet(sortKey, sortDescending, pageSize, page);
            if (result != null) {
                result.setIsCollection(resource.isCollectionResource());
                result.setIsPrimitiveArray(resource.isPrimitiveArray());
                PagingHelper.addPagingParameter(result, pageSize, page);
                // timing..
                final double queryTimeEnd = System.nanoTime();
                // store property view that will be used to render the results
                result.setPropertyView(propertyView.get(securityContext));
                // allow resource to modify result set
                resource.postProcessResultSet(result);
                DecimalFormat decimalFormat = new DecimalFormat("0.000000000", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
                result.setQueryTime(decimalFormat.format((queryTimeEnd - queryTimeStart) / 1000000000.0));
                Writer writer = response.getWriter();
                if (writeBom) {
                    writeUtf8Bom(writer);
                }
                // gson.toJson(result, writer);
                writeCsv(result, writer, propertyView.get(securityContext));
                response.setStatus(HttpServletResponse.SC_OK);
                writer.flush();
                writer.close();
            } else {
                logger.warn("Result was null!");
                int code = HttpServletResponse.SC_NO_CONTENT;
                response.setStatus(code);
                Writer writer = response.getWriter();
                writer.flush();
                writer.close();
            }
            tx.success();
        }
    } catch (FrameworkException frameworkException) {
        // set status
        response.setStatus(frameworkException.getStatus());
    } catch (JsonSyntaxException jsex) {
        logger.warn("JsonSyntaxException in GET", jsex);
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
    } catch (JsonParseException jpex) {
        logger.warn("JsonParseException in GET", jpex);
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
    } catch (Throwable t) {
        logger.warn("Exception in GET", t);
        int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        response.setStatus(code);
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) DecimalFormat(java.text.DecimalFormat) Resource(org.structr.rest.resource.Resource) JsonParseException(com.google.gson.JsonParseException) Result(org.structr.core.Result) RestMethodResult(org.structr.rest.RestMethodResult) JsonSyntaxException(com.google.gson.JsonSyntaxException) Authenticator(org.structr.core.auth.Authenticator) PropertyKey(org.structr.core.property.PropertyKey) Writer(java.io.Writer)

Example 2 with Authenticator

use of org.structr.core.auth.Authenticator in project structr by structr.

the class CsvServlet method doPost.

@Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
    final String fieldSeparatorHeader = request.getHeader(DEFAULT_FIELD_SEPARATOR_HEADER_NAME);
    final char fieldSeparator = (fieldSeparatorHeader == null) ? DEFAULT_FIELD_SEPARATOR : fieldSeparatorHeader.charAt(0);
    final String quoteCharacterHeader = request.getHeader(DEFAULT_QUOTE_CHARACTER_HEADER_NAME);
    final char quoteCharacter = (quoteCharacterHeader == null) ? DEFAULT_QUOTE_CHARACTER : quoteCharacterHeader.charAt(0);
    final String doPeridicCommitHeader = request.getHeader(DEFAULT_PERIODIC_COMMIT_HEADER_NAME);
    final boolean doPeriodicCommit = (doPeridicCommitHeader == null) ? DEFAULT_PERIODIC_COMMIT : Boolean.parseBoolean(doPeridicCommitHeader);
    final String periodicCommitIntervalHeader = request.getHeader(DEFAULT_PERIODIC_COMMIT_INTERVAL_HEADER_NAME);
    final int periodicCommitInterval = (periodicCommitIntervalHeader == null) ? DEFAULT_PERIODIC_COMMIT_INTERVAL : Integer.parseInt(periodicCommitIntervalHeader);
    final String rangeHeader = request.getHeader(DEFAULT_RANGE_HEADER_NAME);
    final List<RestMethodResult> results = new LinkedList<>();
    final Authenticator authenticator;
    final Resource resource;
    try {
        // first thing to do!
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // get reader before initalizing security context
        final Reader input = request.getReader();
        // isolate request authentication in a transaction
        try (final Tx tx = StructrApp.getInstance().tx()) {
            authenticator = config.getAuthenticator();
            securityContext = authenticator.initializeAndExamineRequest(request, response);
            tx.success();
        }
        final App app = StructrApp.getInstance(securityContext);
        if (securityContext != null) {
            // isolate resource authentication
            try (final Tx tx = app.tx()) {
                resource = ResourceHelper.applyViewTransformation(request, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView), propertyView);
                authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
                tx.success();
            }
            // do not send websocket notifications for created objects
            securityContext.setDoTransactionNotifications(false);
            securityContext.disableModificationOfAccessTime();
            securityContext.ignoreResultCount(true);
            securityContext.disableEnsureCardinality();
            final String username = securityContext.getUser(false).getName();
            final long startTime = System.currentTimeMillis();
            final Map<String, Object> data = new LinkedHashMap();
            data.put("type", "CSV_IMPORT_STATUS");
            data.put("subtype", "BEGIN");
            data.put("username", username);
            TransactionCommand.simpleBroadcastGenericMessage(data);
            // isolate doPost
            boolean retry = true;
            while (retry) {
                retry = false;
                final Iterable<JsonInput> csv = CsvHelper.cleanAndParseCSV(securityContext, input, resource.getEntityClass(), fieldSeparator, quoteCharacter, rangeHeader);
                if (resource.createPostTransaction()) {
                    if (doPeriodicCommit) {
                        final List<JsonInput> list = new ArrayList<>();
                        csv.iterator().forEachRemaining(list::add);
                        final List<List<JsonInput>> chunkedCsv = ListUtils.partition(list, periodicCommitInterval);
                        final int totalChunkNo = chunkedCsv.size();
                        int currentChunkNo = 0;
                        for (final List<JsonInput> currentChunk : chunkedCsv) {
                            try (final Tx tx = app.tx()) {
                                currentChunkNo++;
                                for (final JsonInput propertySet : currentChunk) {
                                    handleCsvPropertySet(results, resource, propertySet);
                                }
                                tx.success();
                                logger.info("CSV: Finished importing chunk " + currentChunkNo + " / " + totalChunkNo);
                                final Map<String, Object> chunkMsgData = new LinkedHashMap();
                                chunkMsgData.put("type", "CSV_IMPORT_STATUS");
                                chunkMsgData.put("subtype", "CHUNK");
                                chunkMsgData.put("currentChunkNo", currentChunkNo);
                                chunkMsgData.put("totalChunkNo", totalChunkNo);
                                chunkMsgData.put("username", username);
                                TransactionCommand.simpleBroadcastGenericMessage(chunkMsgData);
                            } catch (RetryException ddex) {
                                retry = true;
                            }
                        }
                    } else {
                        try (final Tx tx = app.tx()) {
                            for (final JsonInput propertySet : csv) {
                                handleCsvPropertySet(results, resource, propertySet);
                            }
                            tx.success();
                        } catch (RetryException ddex) {
                            retry = true;
                        }
                    }
                } else {
                    if (doPeriodicCommit) {
                        logger.warn("Resource auto-creates POST transaction - can not commit periodically!");
                    }
                    try {
                        for (final JsonInput propertySet : csv) {
                            handleCsvPropertySet(results, resource, propertySet);
                        }
                    } catch (RetryException ddex) {
                        retry = true;
                    }
                }
            }
            final long endTime = System.currentTimeMillis();
            DecimalFormat decimalFormat = new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
            final String duration = decimalFormat.format(((endTime - startTime) / 1000.0)) + "s";
            logger.info("CSV: Finished importing CSV data (Time: {})", duration);
            final Map<String, Object> endMsgData = new LinkedHashMap();
            endMsgData.put("type", "CSV_IMPORT_STATUS");
            endMsgData.put("subtype", "END");
            endMsgData.put("duration", duration);
            endMsgData.put("username", username);
            TransactionCommand.simpleBroadcastGenericMessage(endMsgData);
            // set default value for property view
            propertyView.set(securityContext, config.getDefaultPropertyView());
            // isolate write output
            try (final Tx tx = app.tx()) {
                if (!results.isEmpty()) {
                    final RestMethodResult result = results.get(0);
                    final int resultCount = results.size();
                    if (result != null) {
                        if (resultCount > 1) {
                            for (final RestMethodResult r : results) {
                                final GraphObject objectCreated = r.getContent().get(0);
                                if (!result.getContent().contains(objectCreated)) {
                                    result.addContent(objectCreated);
                                }
                            }
                            // remove Location header if more than one object was
                            // written because it may only contain a single URL
                            result.addHeader("Location", null);
                        }
                        result.commitResponse(gson.get(), response);
                    }
                }
                tx.success();
            }
        } else {
            // isolate write output
            try (final Tx tx = app.tx()) {
                new RestMethodResult(HttpServletResponse.SC_FORBIDDEN).commitResponse(gson.get(), response);
                tx.success();
            }
        }
    } catch (FrameworkException frameworkException) {
        // set status & write JSON output
        response.setStatus(frameworkException.getStatus());
        gson.get().toJson(frameworkException, response.getWriter());
        response.getWriter().println();
    } catch (JsonSyntaxException jsex) {
        logger.warn("POST: Invalid JSON syntax", jsex.getMessage());
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + jsex.getMessage()));
    } catch (JsonParseException jpex) {
        logger.warn("Unable to parse JSON string", jpex.getMessage());
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "JsonParseException in POST: " + jpex.getMessage()));
    } catch (UnsupportedOperationException uoe) {
        logger.warn("POST not supported");
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "POST not supported: " + uoe.getMessage()));
    } catch (Throwable t) {
        logger.warn("Exception in POST", t);
        int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + t.getMessage()));
    } finally {
        try {
            // response.getWriter().flush();
            response.getWriter().close();
        } catch (Throwable t) {
            logger.warn("Unable to flush and close response: {}", t.getMessage());
        }
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) Reader(java.io.Reader) GraphObject(org.structr.core.GraphObject) JsonParseException(com.google.gson.JsonParseException) LinkedHashMap(java.util.LinkedHashMap) JsonInput(org.structr.core.JsonInput) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Authenticator(org.structr.core.auth.Authenticator) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) Resource(org.structr.rest.resource.Resource) RetryException(org.structr.api.RetryException) LinkedList(java.util.LinkedList) JsonSyntaxException(com.google.gson.JsonSyntaxException) GraphObject(org.structr.core.GraphObject) RestMethodResult(org.structr.rest.RestMethodResult)

Example 3 with Authenticator

use of org.structr.core.auth.Authenticator in project structr by structr.

the class JsonRestServlet method doPost.

// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="POST">
@Override
protected void doPost(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    final List<RestMethodResult> results = new LinkedList<>();
    final SecurityContext securityContext;
    final Authenticator authenticator;
    final Resource resource;
    try {
        assertInitialized();
        // first thing to do!
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // get reader before initalizing security context
        final String input = IOUtils.toString(request.getReader());
        // isolate request authentication in a transaction
        try (final Tx tx = StructrApp.getInstance().tx()) {
            authenticator = config.getAuthenticator();
            securityContext = authenticator.initializeAndExamineRequest(request, response);
            tx.success();
        }
        final App app = StructrApp.getInstance(securityContext);
        final IJsonInput jsonInput = cleanAndParseJsonString(app, input);
        if (securityContext != null) {
            // isolate resource authentication
            try (final Tx tx = app.tx()) {
                resource = ResourceHelper.applyViewTransformation(request, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView), propertyView);
                authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
                tx.success();
            }
            // isolate doPost
            boolean retry = true;
            while (retry) {
                if (resource.createPostTransaction()) {
                    try (final Tx tx = app.tx()) {
                        for (JsonInput propertySet : jsonInput.getJsonInputs()) {
                            results.add(resource.doPost(convertPropertySetToMap(propertySet)));
                        }
                        tx.success();
                        retry = false;
                    } catch (RetryException ddex) {
                        retry = true;
                    }
                } else {
                    try {
                        for (JsonInput propertySet : jsonInput.getJsonInputs()) {
                            results.add(resource.doPost(convertPropertySetToMap(propertySet)));
                        }
                        retry = false;
                    } catch (RetryException ddex) {
                        retry = true;
                    }
                }
            }
            // set default value for property view
            propertyView.set(securityContext, config.getDefaultPropertyView());
            // isolate write output
            try (final Tx tx = app.tx()) {
                if (!results.isEmpty()) {
                    final RestMethodResult result = results.get(0);
                    final int resultCount = results.size();
                    if (result != null) {
                        if (resultCount > 1) {
                            for (final RestMethodResult r : results) {
                                final GraphObject objectCreated = r.getContent().get(0);
                                if (!result.getContent().contains(objectCreated)) {
                                    result.addContent(objectCreated);
                                }
                            }
                            // remove Location header if more than one object was
                            // written because it may only contain a single URL
                            result.addHeader("Location", null);
                        }
                        result.commitResponse(gson.get(), response);
                    }
                }
                tx.success();
            }
        } else {
            // isolate write output
            try (final Tx tx = app.tx()) {
                new RestMethodResult(HttpServletResponse.SC_FORBIDDEN).commitResponse(gson.get(), response);
                tx.success();
            }
        }
    } catch (FrameworkException frameworkException) {
        // set status & write JSON output
        response.setStatus(frameworkException.getStatus());
        gson.get().toJson(frameworkException, response.getWriter());
        response.getWriter().println();
    } catch (JsonSyntaxException jsex) {
        logger.warn("POST: Invalid JSON syntax", jsex.getMessage());
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + jsex.getMessage()));
    } catch (JsonParseException jpex) {
        logger.warn("Unable to parse JSON string", jpex.getMessage());
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "JsonParseException in POST: " + jpex.getMessage()));
    } catch (UnsupportedOperationException uoe) {
        logger.warn("POST not supported");
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "POST not supported: " + uoe.getMessage()));
    } catch (Throwable t) {
        logger.warn("Exception in POST", t);
        int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + t.getMessage()));
    } finally {
        try {
            // response.getWriter().flush();
            response.getWriter().close();
        } catch (Throwable t) {
            logger.warn("Unable to flush and close response: {}", t.getMessage());
        }
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) Resource(org.structr.rest.resource.Resource) StaticRelationshipResource(org.structr.rest.resource.StaticRelationshipResource) RetryException(org.structr.api.RetryException) GraphObject(org.structr.core.GraphObject) JsonParseException(com.google.gson.JsonParseException) LinkedList(java.util.LinkedList) JsonInput(org.structr.core.JsonInput) IJsonInput(org.structr.core.IJsonInput) JsonSyntaxException(com.google.gson.JsonSyntaxException) SecurityContext(org.structr.common.SecurityContext) IJsonInput(org.structr.core.IJsonInput) RestMethodResult(org.structr.rest.RestMethodResult) Authenticator(org.structr.core.auth.Authenticator)

Example 4 with Authenticator

use of org.structr.core.auth.Authenticator in project structr by structr.

the class JsonRestServlet method doGetOrHead.

private void doGetOrHead(final HttpServletRequest request, final HttpServletResponse response, final boolean returnContent) throws ServletException, IOException {
    SecurityContext securityContext = null;
    Authenticator authenticator = null;
    Result result = null;
    Resource resource = null;
    try {
        // first thing to do!
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // isolate request authentication in a transaction
        try (final Tx tx = StructrApp.getInstance().tx()) {
            authenticator = config.getAuthenticator();
            securityContext = authenticator.initializeAndExamineRequest(request, response);
            tx.success();
        }
        final App app = StructrApp.getInstance(securityContext);
        // set default value for property view
        propertyView.set(securityContext, config.getDefaultPropertyView());
        // evaluate constraints and measure query time
        double queryTimeStart = System.nanoTime();
        // isolate resource authentication
        try (final Tx tx = app.tx()) {
            resource = ResourceHelper.applyViewTransformation(request, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView), propertyView);
            authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
            tx.success();
        }
        // add sorting & paging
        String pageSizeParameter = request.getParameter(REQUEST_PARAMETER_PAGE_SIZE);
        String pageParameter = request.getParameter(REQUEST_PARAMETER_PAGE_NUMBER);
        String sortOrder = request.getParameter(REQUEST_PARAMETER_SORT_ORDER);
        String sortKeyName = request.getParameter(REQUEST_PARAMETER_SORT_KEY);
        String outputDepth = request.getParameter(REQUEST_PARAMTER_OUTPUT_DEPTH);
        boolean sortDescending = (sortOrder != null && "desc".equals(sortOrder.toLowerCase()));
        int pageSize = Services.parseInt(pageSizeParameter, NodeFactory.DEFAULT_PAGE_SIZE);
        int page = Services.parseInt(pageParameter, NodeFactory.DEFAULT_PAGE);
        int depth = Services.parseInt(outputDepth, config.getOutputNestingDepth());
        String baseUrl = request.getRequestURI();
        PropertyKey sortKey = null;
        // set sort key
        if (sortKeyName != null) {
            Class<? extends GraphObject> type = resource.getEntityClass();
            if (type == null) {
                // fallback to default implementation
                // if no type can be determined
                type = AbstractNode.class;
            }
            sortKey = StructrApp.getConfiguration().getPropertyKeyForDatabaseName(type, sortKeyName, false);
        }
        // isolate doGet
        boolean retry = true;
        while (retry) {
            try (final Tx tx = app.tx()) {
                result = resource.doGet(sortKey, sortDescending, pageSize, page);
                tx.success();
                retry = false;
            } catch (RetryException ddex) {
                retry = true;
            }
        }
        if (result == null) {
            throw new FrameworkException(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Unable to retrieve result, check database connection");
        }
        if (returnContent) {
            if (!(resource instanceof StaticRelationshipResource) && !result.isPrimitiveArray() && !result.isEmpty()) {
                result.setIsCollection(resource.isCollectionResource());
                result.setIsPrimitiveArray(resource.isPrimitiveArray());
            }
            PagingHelper.addPagingParameter(result, pageSize, page);
            // timing..
            double queryTimeEnd = System.nanoTime();
            // store property view that will be used to render the results
            result.setPropertyView(propertyView.get(securityContext));
            // allow resource to modify result set
            resource.postProcessResultSet(result);
            DecimalFormat decimalFormat = new DecimalFormat("0.000000000", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
            result.setQueryTime(decimalFormat.format((queryTimeEnd - queryTimeStart) / 1000000000.0));
            if (outputDepth != null) {
                result.setOutputNestingDepth(depth);
            }
            String accept = request.getHeader("Accept");
            if (accept != null && accept.contains("text/html")) {
                final StreamingHtmlWriter htmlStreamer = new StreamingHtmlWriter(this.propertyView, indentJson, depth);
                // isolate write output
                try (final Tx tx = app.tx()) {
                    // no trailing semicolon so we dont trip MimeTypes.getContentTypeWithoutCharset
                    response.setContentType("text/html; charset=utf-8");
                    final Writer writer = response.getWriter();
                    htmlStreamer.stream(securityContext, writer, result, baseUrl);
                    // useful newline
                    writer.append("\n");
                    tx.success();
                }
            } else {
                final StreamingJsonWriter jsonStreamer = new StreamingJsonWriter(this.propertyView, indentJson, depth);
                // isolate write output
                try (final Tx tx = app.tx()) {
                    // no trailing semicolon so we dont trip MimeTypes.getContentTypeWithoutCharset
                    response.setContentType("application/json; charset=utf-8");
                    final Writer writer = response.getWriter();
                    jsonStreamer.stream(securityContext, writer, result, baseUrl);
                    // useful newline
                    writer.append("\n");
                    tx.success();
                }
            }
        }
        response.setStatus(HttpServletResponse.SC_OK);
    } catch (FrameworkException frameworkException) {
        // set status & write JSON output
        response.setStatus(frameworkException.getStatus());
        gson.get().toJson(frameworkException, response.getWriter());
        response.getWriter().println();
    } catch (JsonSyntaxException jsex) {
        logger.warn("JsonSyntaxException in GET", jsex);
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "Json syntax exception in GET: " + jsex.getMessage()));
    } catch (JsonParseException jpex) {
        logger.warn("JsonParseException in GET", jpex);
        int code = HttpServletResponse.SC_BAD_REQUEST;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "Parser exception in GET: " + jpex.getMessage()));
    } catch (Throwable t) {
        logger.warn("Exception in GET (URI: {})", securityContext != null ? securityContext.getCompoundRequestURI() : "(null SecurityContext)");
        logger.warn(" => Error thrown: ", t);
        int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        response.setStatus(code);
        response.getWriter().append(RestMethodResult.jsonError(code, "Exception in GET: " + t.getMessage()));
    } finally {
        try {
            // response.getWriter().flush();
            response.getWriter().close();
        } catch (Throwable t) {
            logger.warn("Unable to flush and close response: {}", t.getMessage());
        }
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) DecimalFormat(java.text.DecimalFormat) Resource(org.structr.rest.resource.Resource) StaticRelationshipResource(org.structr.rest.resource.StaticRelationshipResource) StaticRelationshipResource(org.structr.rest.resource.StaticRelationshipResource) StreamingHtmlWriter(org.structr.rest.serialization.StreamingHtmlWriter) RetryException(org.structr.api.RetryException) JsonParseException(com.google.gson.JsonParseException) Result(org.structr.core.Result) RestMethodResult(org.structr.rest.RestMethodResult) JsonSyntaxException(com.google.gson.JsonSyntaxException) StreamingJsonWriter(org.structr.rest.serialization.StreamingJsonWriter) SecurityContext(org.structr.common.SecurityContext) Authenticator(org.structr.core.auth.Authenticator) PropertyKey(org.structr.core.property.PropertyKey) Writer(java.io.Writer) StreamingHtmlWriter(org.structr.rest.serialization.StreamingHtmlWriter) StreamingJsonWriter(org.structr.rest.serialization.StreamingJsonWriter)

Example 5 with Authenticator

use of org.structr.core.auth.Authenticator in project structr by structr.

the class HtmlServlet method doGet.

@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) {
    final Authenticator auth = getConfig().getAuthenticator();
    List<Page> pages = null;
    boolean requestUriContainsUuids = false;
    SecurityContext securityContext;
    final App app;
    try {
        assertInitialized();
        final String path = request.getPathInfo() != null ? request.getPathInfo() : "/";
        // check for registration (has its own tx because of write access
        if (checkRegistration(auth, request, response, path)) {
            return;
        }
        // check for registration (has its own tx because of write access
        if (checkResetPassword(auth, request, response, path)) {
            return;
        }
        // isolate request authentication in a transaction
        try (final Tx tx = StructrApp.getInstance().tx()) {
            securityContext = auth.initializeAndExamineRequest(request, response);
            tx.success();
        } catch (AuthenticationException aex) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        app = StructrApp.getInstance(securityContext);
        try (final Tx tx = app.tx()) {
            // Ensure access mode is frontend
            securityContext.setAccessMode(AccessMode.Frontend);
            request.setCharacterEncoding("UTF-8");
            // Important: Set character encoding before calling response.getWriter() !!, see Servlet Spec 5.4
            response.setCharacterEncoding("UTF-8");
            boolean dontCache = false;
            logger.debug("Path info {}", path);
            // don't continue on redirects
            if (response.getStatus() == 302) {
                tx.success();
                return;
            }
            final Principal user = securityContext.getUser(false);
            if (user != null) {
                // Don't cache if a user is logged in
                dontCache = true;
            }
            final RenderContext renderContext = RenderContext.getInstance(securityContext, request, response);
            renderContext.setResourceProvider(config.getResourceProvider());
            final EditMode edit = renderContext.getEditMode(user);
            DOMNode rootElement = null;
            AbstractNode dataNode = null;
            final String[] uriParts = PathHelper.getParts(path);
            if ((uriParts == null) || (uriParts.length == 0)) {
                // find a visible page
                rootElement = findIndexPage(securityContext, pages, edit);
                logger.debug("No path supplied, trying to find index page");
            } else {
                if (rootElement == null) {
                    rootElement = findPage(securityContext, pages, path, edit);
                } else {
                    dontCache = true;
                }
            }
            if (rootElement == null) {
                // No page found
                // In case of a file, try to find a file with the query string in the filename
                final String queryString = request.getQueryString();
                // Look for a file, first include the query string
                File file = findFile(securityContext, request, path + (queryString != null ? "?" + queryString : ""));
                // If no file with query string in the file name found, try without query string
                if (file == null) {
                    file = findFile(securityContext, request, path);
                }
                if (file != null) {
                    streamFile(securityContext, file, request, response, edit);
                    tx.success();
                    return;
                }
                if (uriParts != null) {
                    // store remaining path parts in request
                    final Matcher matcher = threadLocalUUIDMatcher.get();
                    for (int i = 0; i < uriParts.length; i++) {
                        request.setAttribute(uriParts[i], i);
                        matcher.reset(uriParts[i]);
                        // set to "true" if part matches UUID pattern
                        requestUriContainsUuids |= matcher.matches();
                    }
                }
                if (!requestUriContainsUuids) {
                    // Try to find a data node by name
                    dataNode = findFirstNodeByName(securityContext, request, path);
                } else {
                    dataNode = findNodeByUuid(securityContext, PathHelper.getName(path));
                }
                // if (dataNode != null && !(dataNode instanceof Linkable)) {
                if (dataNode != null) {
                    // Last path part matches a data node
                    // Remove last path part and try again searching for a page
                    // clear possible entry points
                    request.removeAttribute(POSSIBLE_ENTRY_POINTS_KEY);
                    rootElement = findPage(securityContext, pages, StringUtils.substringBeforeLast(path, PathHelper.PATH_SEP), edit);
                    renderContext.setDetailsDataObject(dataNode);
                    // Start rendering on data node
                    if (rootElement == null && dataNode instanceof DOMNode) {
                        // check visibleForSite here as well
                        if (!(dataNode instanceof Page) || isVisibleForSite(request, (Page) dataNode)) {
                            rootElement = ((DOMNode) dataNode);
                        }
                    }
                }
            }
            // look for pages with HTTP Basic Authentication (must be done as superuser)
            if (rootElement == null) {
                final HttpBasicAuthResult authResult = checkHttpBasicAuth(request, response, path);
                switch(authResult.authState()) {
                    // Element with Basic Auth found and authentication succeeded
                    case Authenticated:
                        final Linkable result = authResult.getRootElement();
                        if (result instanceof Page) {
                            rootElement = (DOMNode) result;
                            securityContext = authResult.getSecurityContext();
                            renderContext.pushSecurityContext(securityContext);
                        } else if (result instanceof File) {
                            streamFile(authResult.getSecurityContext(), (File) result, request, response, EditMode.NONE);
                            tx.success();
                            return;
                        }
                        break;
                    // Page with Basic Auth found but not yet authenticated
                    case MustAuthenticate:
                        final Page errorPage = StructrApp.getInstance().nodeQuery(Page.class).and(StructrApp.key(Page.class, "showOnErrorCodes"), "401", false).getFirst();
                        if (errorPage != null && isVisibleForSite(request, errorPage)) {
                            // set error page
                            rootElement = errorPage;
                            // don't cache the error page
                            dontCache = true;
                        } else {
                            // send error
                            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                            tx.success();
                            return;
                        }
                        break;
                    // no Basic Auth for given path, go on
                    case NoBasicAuth:
                        break;
                }
            }
            // Still nothing found, do error handling
            if (rootElement == null) {
                rootElement = notFound(response, securityContext);
            }
            if (rootElement == null) {
                tx.success();
                return;
            }
            // check dont cache flag on page (if root element is a page)
            // but don't modify true to false
            dontCache |= rootElement.dontCache();
            if (EditMode.WIDGET.equals(edit) || dontCache) {
                setNoCacheHeaders(response);
            }
            if (!securityContext.isVisible(rootElement)) {
                rootElement = notFound(response, securityContext);
                if (rootElement == null) {
                    tx.success();
                    return;
                }
            } else {
                if (!EditMode.WIDGET.equals(edit) && !dontCache && notModifiedSince(request, response, rootElement, dontCache)) {
                    ServletOutputStream out = response.getOutputStream();
                    out.flush();
                    // response.flushBuffer();
                    out.close();
                } else {
                    // prepare response
                    response.setCharacterEncoding("UTF-8");
                    String contentType = rootElement.getProperty(StructrApp.key(Page.class, "contentType"));
                    if (contentType == null) {
                        // Default
                        contentType = "text/html;charset=UTF-8";
                    }
                    if (contentType.equals("text/html")) {
                        contentType = contentType.concat(";charset=UTF-8");
                    }
                    response.setContentType(contentType);
                    setCustomResponseHeaders(response);
                    final boolean createsRawData = rootElement.getProperty(StructrApp.key(Page.class, "pageCreatesRawData"));
                    // async or not?
                    if (isAsync && !createsRawData) {
                        final AsyncContext async = request.startAsync();
                        final ServletOutputStream out = async.getResponse().getOutputStream();
                        final AtomicBoolean finished = new AtomicBoolean(false);
                        final DOMNode rootNode = rootElement;
                        threadPool.submit(new Runnable() {

                            @Override
                            public void run() {
                                try (final Tx tx = app.tx()) {
                                    // render
                                    rootNode.render(renderContext, 0);
                                    finished.set(true);
                                    tx.success();
                                } catch (Throwable t) {
                                    t.printStackTrace();
                                    logger.warn("Error while rendering page {}: {}", rootNode.getName(), t.getMessage());
                                    try {
                                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                                        finished.set(true);
                                    } catch (IOException ex) {
                                        logger.warn("", ex);
                                    }
                                }
                            }
                        });
                        // start output write listener
                        out.setWriteListener(new WriteListener() {

                            @Override
                            public void onWritePossible() throws IOException {
                                try {
                                    final Queue<String> queue = renderContext.getBuffer().getQueue();
                                    while (out.isReady()) {
                                        String buffer = null;
                                        synchronized (queue) {
                                            buffer = queue.poll();
                                        }
                                        if (buffer != null) {
                                            out.print(buffer);
                                        } else {
                                            if (finished.get()) {
                                                async.complete();
                                                // prevent this block from being called again
                                                break;
                                            }
                                            Thread.sleep(1);
                                        }
                                    }
                                } catch (Throwable t) {
                                    logger.warn("", t);
                                }
                            }

                            @Override
                            public void onError(Throwable t) {
                                logger.warn("", t);
                            }
                        });
                    } else {
                        final StringRenderBuffer buffer = new StringRenderBuffer();
                        renderContext.setBuffer(buffer);
                        // render
                        rootElement.render(renderContext, 0);
                        try {
                            response.getOutputStream().write(buffer.getBuffer().toString().getBytes("utf-8"));
                            response.getOutputStream().flush();
                            response.getOutputStream().close();
                        } catch (IOException ioex) {
                            logger.warn("", ioex);
                        }
                    }
                }
            }
            tx.success();
        } catch (FrameworkException fex) {
            logger.error("Exception while processing request: {}", fex.getMessage());
        }
    } catch (FrameworkException fex) {
        logger.error("Exception while processing request: {}", fex.getMessage());
        UiAuthenticator.writeFrameworkException(response, fex);
    } catch (IOException ioex) {
        logger.error("Exception while processing request: {}", ioex.getMessage());
        UiAuthenticator.writeInternalServerError(response);
    }
}
Also used : App(org.structr.core.app.App) StructrApp(org.structr.core.app.StructrApp) StringRenderBuffer(org.structr.web.common.StringRenderBuffer) AuthenticationException(org.structr.core.auth.exception.AuthenticationException) AbstractNode(org.structr.core.entity.AbstractNode) Matcher(java.util.regex.Matcher) ThreadLocalMatcher(org.structr.common.ThreadLocalMatcher) ServletOutputStream(javax.servlet.ServletOutputStream) Page(org.structr.web.entity.dom.Page) AsyncContext(javax.servlet.AsyncContext) DOMNode(org.structr.web.entity.dom.DOMNode) WriteListener(javax.servlet.WriteListener) Queue(java.util.Queue) UiAuthenticator(org.structr.web.auth.UiAuthenticator) Authenticator(org.structr.core.auth.Authenticator) RenderContext(org.structr.web.common.RenderContext) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) SecurityContext(org.structr.common.SecurityContext) EditMode(org.structr.web.common.RenderContext.EditMode) Linkable(org.structr.web.entity.Linkable) AbstractFile(org.structr.web.entity.AbstractFile) File(org.structr.web.entity.File) Principal(org.structr.core.entity.Principal)

Aggregations

Authenticator (org.structr.core.auth.Authenticator)14 FrameworkException (org.structr.common.error.FrameworkException)12 Tx (org.structr.core.graph.Tx)12 App (org.structr.core.app.App)10 StructrApp (org.structr.core.app.StructrApp)10 SecurityContext (org.structr.common.SecurityContext)9 RestMethodResult (org.structr.rest.RestMethodResult)8 JsonParseException (com.google.gson.JsonParseException)7 JsonSyntaxException (com.google.gson.JsonSyntaxException)7 Resource (org.structr.rest.resource.Resource)7 RetryException (org.structr.api.RetryException)6 Principal (org.structr.core.entity.Principal)5 StaticRelationshipResource (org.structr.rest.resource.StaticRelationshipResource)5 UiAuthenticator (org.structr.web.auth.UiAuthenticator)4 IOException (java.io.IOException)3 Writer (java.io.Writer)3 DecimalFormat (java.text.DecimalFormat)3 LinkedHashMap (java.util.LinkedHashMap)2 LinkedList (java.util.LinkedList)2 Matcher (java.util.regex.Matcher)2