Java tutorial
/* *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; } }; }