cz.muni.fi.editor.services.api.requests.RequestServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for cz.muni.fi.editor.services.api.requests.RequestServiceImpl.java

Source

/*
*Copyright  2016 Dominik Szalai (emptulik@gmail.com)
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/
/*
 * Copyright  2016 Dominik Szalai (emptulik@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cz.muni.fi.editor.services.api.requests;

import cz.muni.fi.editor.api.dto.OrganizationDTO;
import cz.muni.fi.editor.api.dto.RequestDTO;
import cz.muni.fi.editor.api.exceptions.FieldException;
import cz.muni.fi.editor.api.RequestService;
import cz.muni.fi.editor.database.dao.OrganizationDAO;
import cz.muni.fi.editor.database.dao.RequestDAO;
import cz.muni.fi.editor.database.domain.requests.Request;
import cz.muni.fi.editor.database.domain.requests.RequestState;
import cz.muni.fi.editor.database.domain.user.Organization;
import cz.muni.fi.editor.database.domain.user.User;
import cz.muni.fi.editor.services.commons.Mapper;
import cz.muni.fi.editor.services.commons.events.EOrganizationCreate;
import cz.muni.fi.editor.services.commons.events.EOrganizationJoined;
import cz.muni.fi.editor.services.commons.events.ERequestCreated;
import cz.muni.fi.editor.services.commons.security.EditorAccessVoter;
import cz.muni.fi.editor.services.commons.security.SecurityService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created by Dominik Szalai - emptulik at gmail.com on 24.8.2016.
 */
@Log4j2
@Service
public class RequestServiceImpl implements RequestService, ApplicationEventPublisherAware {
    @Autowired
    private RequestDAO requestDAO;
    @Autowired
    private OrganizationDAO organizationDAO;
    @Autowired
    private Mapper mapper;
    @Autowired
    private EditorAccessVoter editorAccessVoter;
    @Autowired
    private SecurityService securityService;

    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private ApproverRepository approverRepository;

    @Override
    @Transactional(readOnly = true)
    public List<RequestDTO> getUnApproved() throws AccessDeniedException {
        return requestDAO.getUnApproved().stream().filter(canView).map(r -> mapper.map(r, RequestDTO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void approve(RequestDTO requestDTO)
            throws IllegalArgumentException, AccessDeniedException, FieldException {
        Request dao = requestDAO.getById(requestDTO.getId());
        verifyAndCheckAccess(dao);

        try {
            approverRepository.getApprover(Class.forName(dao.getClazz()), dao.getAction()).approve(dao);
        } catch (ClassNotFoundException e) {
            log.error(e);
        }
    }

    @Override
    @Transactional
    public void deny(RequestDTO requestDTO) throws IllegalArgumentException, AccessDeniedException, FieldException {
        Request dao = requestDAO.getById(requestDTO.getId());
        verifyAndCheckAccess(dao);

        try {
            approverRepository.getDecliner(Class.forName(dao.getClazz()), dao.getAction()).decline(dao);
        } catch (ClassNotFoundException e) {
            log.error(e);
        }
    }

    private void verifyAndCheckAccess(Request request) throws IllegalArgumentException, AccessDeniedException {
        if (request.getState().equals(RequestState.ACCEPTED)) {
            throw new IllegalArgumentException(
                    MessageFormat.format("Cannot approve request with id {0}. Request has wrong state {1}",
                            request.getId(), request.getState()));
        }

        if (!canView.test(request)) {
            throw new AccessDeniedException(
                    MessageFormat.format("Not allowed to see request {0}", request.getId()));
        }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @TransactionalEventListener
    @Async
    @Transactional
    public void createOrganization(EOrganizationCreate organizationCreatedEvent) {
        Request request = new Request();
        request.setAction("create");
        request.setTargetId(organizationCreatedEvent.getOrganizationDTO().getId());
        request.setClazz(OrganizationDTO.class.getName());
        request.setState(RequestState.PENDING);
        request.setRequestDate(LocalDateTime.now());
        request.setRequestor(mapper.map(organizationCreatedEvent.getActor(), User.class));

        requestDAO.create(request);

        applicationEventPublisher
                .publishEvent(new ERequestCreated(this, organizationCreatedEvent.getActor(), request));
    }

    @TransactionalEventListener
    @Async
    @Transactional
    public void joinOrganization(EOrganizationJoined eOrganizationJoined) {
        Request request = new Request();
        request.setAction("join");
        request.setTargetId(eOrganizationJoined.getOrganization().getId());
        request.setClazz(OrganizationDTO.class.getName());
        request.setState(RequestState.PENDING);
        request.setRequestDate(LocalDateTime.now());
        request.setRequestor(mapper.map(eOrganizationJoined.getActor(), User.class));

        requestDAO.create(request);

        applicationEventPublisher.publishEvent(new ERequestCreated(this, eOrganizationJoined.getActor(), request));
    }

    private Predicate<Request> canView = new Predicate<Request>() {
        @Override
        public boolean test(Request request) {
            if (request.getClazz().equals(OrganizationDTO.class.getName())) {
                Organization org = organizationDAO.getById(request.getTargetId());
                if (request.getAction().equals("join")) {
                    if (editorAccessVoter.isOwner(org.getId(), securityService.getPrincipal())) {
                        log.info("Current user {} is owner of {}, request {} will be added to output",
                                securityService.getPrincipal().getId(), org.getId(), request.getId());

                        return true;
                    } else {
                        log.info("Current user {} is NOT owner of {}, request {} WONT BE added to output",
                                securityService.getPrincipal().getId(), org.getId(), request.getId());

                        return false;
                    }
                } else if (request.getAction().equals("create")
                        && editorAccessVoter.isOwner(1L, securityService.getPrincipal())) {
                    log.info("current user is owner, create-org request {} added to output", org.getId());

                    return true;
                } else {
                    log.info("current user is NOT owner, create-org request {} NOT added to output", org.getId());
                    return false;
                }
            }

            return false;
        }
    };

}