alfio.controller.api.admin.ResourceController.java Source code

Java tutorial

Introduction

Here is the source code for alfio.controller.api.admin.ResourceController.java

Source

/**
 * This file is part of alf.io.
 *
 * alf.io is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * alf.io is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with alf.io.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * This file is part of alf.io.
 * <p>
 * alf.io is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <p>
 * alf.io is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with alf.io.  If not, see <http://www.gnu.org/licenses/>.
 */
package alfio.controller.api.admin;

import alfio.controller.support.TemplateProcessor;
import alfio.manager.FileUploadManager;
import alfio.manager.UploadedResourceManager;
import alfio.manager.user.UserManager;
import alfio.model.Event;
import alfio.model.UploadedResource;
import alfio.model.modification.UploadBase64FileModification;
import alfio.model.user.Organization;
import alfio.repository.EventRepository;
import alfio.repository.user.OrganizationRepository;
import alfio.util.TemplateManager;
import alfio.util.TemplateResource;
import com.samskivert.mustache.MustacheException;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.springframework.web.bind.annotation.RequestMethod.POST;

@RestController
@RequestMapping("/admin/api")
public class ResourceController {

    private final UploadedResourceManager uploadedResourceManager;
    private final UserManager userManager;
    private final EventRepository eventRepository;
    private final MessageSource messageSource;
    private final TemplateManager templateManager;
    private final OrganizationRepository organizationRepository;
    private final FileUploadManager fileUploadManager;

    @Autowired
    public ResourceController(UploadedResourceManager uploadedResourceManager, UserManager userManager,
            EventRepository eventRepository, MessageSource messageSource, TemplateManager templateManager,
            OrganizationRepository organizationRepository, FileUploadManager fileUploadManager) {
        this.uploadedResourceManager = uploadedResourceManager;
        this.userManager = userManager;
        this.eventRepository = eventRepository;
        this.messageSource = messageSource;
        this.templateManager = templateManager;
        this.organizationRepository = organizationRepository;
        this.fileUploadManager = fileUploadManager;
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handleSyntaxError(Exception ex) {
        Optional<String> cause = Optional.ofNullable(ex.getCause()).filter(MustacheException.class::isInstance)
                .map(Throwable::getMessage);
        if (cause.isPresent()) {
            return cause.get();
        }
        return "Something went wrong. Please check the syntax and retry";
    }

    @RequestMapping(value = "/overridable-template/", method = RequestMethod.GET)
    public List<TemplateResource> getOverridableTemplates() {
        return Stream.of(TemplateResource.values()).filter(TemplateResource::overridable)
                .collect(Collectors.toList());
    }

    @RequestMapping(value = "/overridable-template/{name}/{locale}", method = RequestMethod.GET)
    public void getTemplate(@PathVariable("name") TemplateResource name, @PathVariable("locale") String locale,
            HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try (InputStream is = new ClassPathResource(name.classPath()).getInputStream()) {
            StreamUtils.copy(is, os);
        }
        Locale loc = Locale.forLanguageTag(locale);
        String template = new String(os.toByteArray(), StandardCharsets.UTF_8);

        response.setContentType("text/plain");
        response.getWriter().print(TemplateManager.translate(template, loc, messageSource));
    }

    @RequestMapping(value = "/overridable-template/{name}/{locale}/preview", method = RequestMethod.POST)
    public void previewTemplate(@PathVariable("name") TemplateResource name, @PathVariable("locale") String locale,
            @RequestParam(required = false, value = "organizationId") Integer organizationId,
            @RequestParam(required = false, value = "eventId") Integer eventId,
            @RequestBody UploadBase64FileModification template, Principal principal, HttpServletResponse response)
            throws IOException {

        Locale loc = Locale.forLanguageTag(locale);

        if (organizationId != null && eventId != null) {
            checkAccess(organizationId, eventId, principal);
            Event event = eventRepository.findById(eventId);
            Organization organization = organizationRepository.getById(organizationId);
            Optional<TemplateResource.ImageData> image = TemplateProcessor.extractImageModel(event,
                    fileUploadManager);
            Map<String, Object> model = name.prepareSampleModel(organization, event, image);
            String renderedTemplate = templateManager.renderString(template.getFileAsString(), model, loc,
                    name.getTemplateOutput());
            if ("text/plain".equals(name.getRenderedContentType())) {
                response.addHeader("Content-Disposition", "attachment; filename=" + name.name() + ".txt");
                response.setContentType("text/plain");
                response.setCharacterEncoding("UTF-8");
                try (OutputStream os = response.getOutputStream()) {
                    StreamUtils.copy(renderedTemplate, StandardCharsets.UTF_8, os);
                }
            } else if ("application/pdf".equals(name.getRenderedContentType())) {
                response.setContentType("application/pdf");
                response.addHeader("Content-Disposition", "attachment; filename=" + name.name() + ".pdf");
                try (OutputStream os = response.getOutputStream()) {
                    TemplateProcessor.prepareItextRenderer(renderedTemplate).createPDF(os);
                }
            } else {
                throw new IllegalStateException("cannot enter here!");
            }
        }
    }

    //------------------

    @RequestMapping(value = "/resource/", method = RequestMethod.GET)
    public List<UploadedResource> findAll(Principal principal) {
        checkAccess(principal);
        return uploadedResourceManager.findAll();
    }

    @RequestMapping(value = "/resource-organization/{organizationId}", method = RequestMethod.GET)
    public List<UploadedResource> findAllForOrganization(@PathVariable("organizationId") int organizationId,
            Principal principal) {
        checkAccess(organizationId, principal);
        return uploadedResourceManager.findAll(organizationId);
    }

    @RequestMapping(value = "/resource-event/{organizationId}/{eventId}", method = RequestMethod.GET)
    public List<UploadedResource> findAllForEvent(@PathVariable("organizationId") int organizationId,
            @PathVariable("eventId") int eventId, Principal principal) {
        checkAccess(organizationId, eventId, principal);
        return uploadedResourceManager.findAll(organizationId, eventId);
    }

    //------------------

    @RequestMapping(value = "/resource/{name}/metadata", method = RequestMethod.GET)
    public ResponseEntity<UploadedResource> getMetadata(@PathVariable("name") String name, Principal principal) {
        checkAccess(principal);
        if (uploadedResourceManager.hasResource(name)) {
            return new ResponseEntity<>(uploadedResourceManager.get(name), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    @RequestMapping(value = "/resource-organization/{organizationId}/{name}/metadata", method = RequestMethod.GET)
    public ResponseEntity<UploadedResource> getMetadata(@PathVariable("organizationId") int organizationId,
            @PathVariable("name") String name, Principal principal) {
        checkAccess(organizationId, principal);
        if (uploadedResourceManager.hasResource(organizationId, name)) {
            return new ResponseEntity<>(uploadedResourceManager.get(organizationId, name), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    @RequestMapping(value = "/resource-event/{organizationId}/{eventId}/{name}/metadata", method = RequestMethod.GET)
    public ResponseEntity<UploadedResource> getMetadata(@PathVariable("organizationId") int organizationId,
            @PathVariable("eventId") int eventId, @PathVariable("name") String name, Principal principal) {
        checkAccess(organizationId, eventId, principal);
        if (uploadedResourceManager.hasResource(organizationId, eventId, name)) {
            return new ResponseEntity<>(uploadedResourceManager.get(organizationId, eventId, name), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    //------------------

    @RequestMapping(value = "/resource/", method = POST)
    public void uploadFile(@RequestBody UploadBase64FileModification upload, Principal principal) {
        checkAccess(principal);
        uploadedResourceManager.saveResource(upload);
    }

    @RequestMapping(value = "/resource-organization/{organizationId}/", method = POST)
    public void uploadFile(@PathVariable("organizationId") int organizationId,
            @RequestBody UploadBase64FileModification upload, Principal principal) {
        checkAccess(organizationId, principal);
        uploadedResourceManager.saveResource(organizationId, upload);
    }

    @RequestMapping(value = "/resource-event/{organizationId}/{eventId}/", method = POST)
    public void uploadFile(@PathVariable("organizationId") int organizationId, @PathVariable("eventId") int eventId,
            @RequestBody UploadBase64FileModification upload, Principal principal) {
        checkAccess(organizationId, eventId, principal);
        uploadedResourceManager.saveResource(organizationId, eventId, upload);
    }

    //------------------
    @RequestMapping(value = "/resource/{name:.*}", method = RequestMethod.GET)
    public void outputContent(@PathVariable("name") String name, Principal principal, HttpServletResponse response)
            throws IOException {
        checkAccess(principal);
        UploadedResource metadata = uploadedResourceManager.get(name);
        try (OutputStream os = response.getOutputStream()) {
            response.setContentType(metadata.getContentType());
            response.setContentLength(metadata.getContentSize());
            uploadedResourceManager.outputResource(name, os);
        }
    }

    @RequestMapping(value = "/resource-organization/{organizationId}/{name:.*}", method = RequestMethod.GET)
    public void outputContent(@PathVariable("organizationId") int organizationId, @PathVariable("name") String name,
            Principal principal, HttpServletResponse response) throws IOException {
        checkAccess(organizationId, principal);
        UploadedResource metadata = uploadedResourceManager.get(organizationId, name);
        try (OutputStream os = response.getOutputStream()) {
            response.setContentType(metadata.getContentType());
            response.setContentLength(metadata.getContentSize());
            uploadedResourceManager.outputResource(organizationId, name, os);
        }
    }

    @RequestMapping(value = "/resource-event/{organizationId}/{eventId}/{name:.*}", method = RequestMethod.GET)
    public void outputContent(@PathVariable("organizationId") int organizationId,
            @PathVariable("eventId") int eventId, @PathVariable("name") String name, Principal principal,
            HttpServletResponse response) throws IOException {
        checkAccess(organizationId, eventId, principal);
        UploadedResource metadata = uploadedResourceManager.get(organizationId, eventId, name);
        try (OutputStream os = response.getOutputStream()) {
            response.setContentType(metadata.getContentType());
            response.setContentLength(metadata.getContentSize());
            uploadedResourceManager.outputResource(organizationId, eventId, name, os);
        }
    }

    //------------------

    @RequestMapping(value = "/resource/{name:.*}", method = RequestMethod.DELETE)
    public void delete(@PathVariable("name") String name, Principal principal) {
        checkAccess(principal);
        uploadedResourceManager.deleteResource(name);
    }

    @RequestMapping(value = "/resource-organization/{organizationId}/{name:.*}", method = RequestMethod.DELETE)
    public void delete(@PathVariable("organizationId") int organizationId, @PathVariable("name") String name,
            Principal principal) {
        checkAccess(organizationId, principal);
        uploadedResourceManager.deleteResource(organizationId, name);
    }

    @RequestMapping(value = "/resource-event/{organizationId}/{eventId}/{name:.*}", method = RequestMethod.DELETE)
    public void delete(@PathVariable("organizationId") int organizationId, @PathVariable("eventId") int eventId,
            @PathVariable("name") String name, Principal principal) {
        checkAccess(organizationId, eventId, principal);
        uploadedResourceManager.deleteResource(organizationId, eventId, name);
    }

    //------------------

    private void checkAccess(Principal principal) {
        Validate.isTrue(userManager.isAdmin(userManager.findUserByUsername(principal.getName())));
    }

    private void checkAccess(int organizationId, Principal principal) {
        Validate.isTrue(userManager.isOwnerOfOrganization(userManager.findUserByUsername(principal.getName()),
                organizationId));
    }

    private void checkAccess(int organizationId, int eventId, Principal principal) {
        Validate.isTrue(eventRepository.findById(eventId).getOrganizationId() == organizationId && userManager
                .isOwnerOfOrganization(userManager.findUserByUsername(principal.getName()), organizationId));
    }
}