001/*
002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Funsho David
018 */
019
020package org.nuxeo.ecm.restapi.server.jaxrs;
021
022import java.io.IOException;
023import java.io.Serializable;
024import java.util.Map;
025
026import javax.ws.rs.Consumes;
027import javax.ws.rs.POST;
028import javax.ws.rs.Path;
029import javax.ws.rs.PathParam;
030import javax.ws.rs.Produces;
031import javax.ws.rs.core.MediaType;
032import javax.ws.rs.core.Response;
033
034import org.apache.logging.log4j.LogManager;
035import org.apache.logging.log4j.Logger;
036import org.nuxeo.ecm.core.bulk.BulkAdminService;
037import org.nuxeo.ecm.core.bulk.BulkService;
038import org.nuxeo.ecm.core.bulk.io.BulkParameters;
039import org.nuxeo.ecm.core.bulk.message.BulkCommand;
040import org.nuxeo.ecm.core.bulk.message.BulkStatus;
041import org.nuxeo.ecm.restapi.server.jaxrs.adapters.AuditAdapter;
042import org.nuxeo.ecm.webengine.model.WebObject;
043import org.nuxeo.ecm.webengine.model.impl.DefaultObject;
044import org.nuxeo.lib.stream.log.Name;
045import org.nuxeo.runtime.api.Framework;
046
047/**
048 * Bulk endpoint to perform bulk actions on a set of documents.
049 *
050 * @since 10.3
051 */
052@WebObject(type = "bulkAction")
053public class BulkActionObject extends DefaultObject {
054
055    private static Logger log = LogManager.getLogger(BulkActionObject.class);
056
057    protected String query;
058
059    protected String scroller = null;
060
061    @Override
062    public void initialize(Object... args) {
063        query = (String) args[0];
064        if (args.length == 2 && args[1] != null) {
065            scroller = (String) args[1];
066        }
067    }
068
069    @POST
070    @Path("{actionId}")
071    @Consumes(MediaType.APPLICATION_JSON)
072    @Produces(MediaType.APPLICATION_JSON)
073    public Response executeBulkAction(@PathParam("actionId") String actionId, String actionParams)
074            throws IOException {
075        BulkAdminService admin = Framework.getService(BulkAdminService.class);
076        String actionName = Name.ofId(actionId).getUrn();
077        if (!admin.getActions().contains(actionName)) {
078            log.debug("Action not found, id: {}, name: {}.", actionId, actionName);
079            return Response.status(Response.Status.BAD_REQUEST).build();
080        }
081        if (!admin.isHttpEnabled(actionName) && !getContext().getPrincipal().isAdministrator()) {
082            log.debug("Action name: {} is not exposed to HTTP", actionId);
083            return Response.status(Response.Status.FORBIDDEN).build();
084        }
085
086        String repository = getContext().getCoreSession().getRepositoryName();
087        String username = getContext().getPrincipal().getName();
088        Map<String, Serializable> params = BulkParameters.paramsToMap(actionParams);
089
090        BulkCommand command = new BulkCommand.Builder(actionName, query, username).repository(repository)
091                                                                                  .params(params)
092                                                                                  .scroller(scroller)
093                                                                                  .build();
094        BulkService service = Framework.getService(BulkService.class);
095        String commandId = service.submit(command);
096        BulkStatus status = service.getStatus(commandId);
097        log.debug("Action {} submitted in commandId {}", actionId, commandId);
098        return Response.status(Response.Status.ACCEPTED).entity(status).build();
099    }
100}