Subversion Repositories SmartDukaan

Rev

Blame | Last modification | View Log | RSS feed

package com.spice.profitmandi.service.cs;

import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.CustomRetailer;
import com.spice.profitmandi.dao.entity.cs.DemoPartnerAccess;
import com.spice.profitmandi.dao.repository.cs.CsService;
import com.spice.profitmandi.dao.repository.cs.DemoPartnerAccessRepository;
import com.spice.profitmandi.dao.repository.cs.DemoPartnerAccessService;
import com.spice.profitmandi.service.AdminUser;
import com.spice.profitmandi.service.user.RetailerService;
import com.spice.profitmandi.web.config.AppConfig;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Local-database integration tests (rolled back) for demo partner access: a grant opens the partner
 * for the sales person without ever entering the shared position mapping.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {AppConfig.class})
@Transactional
public class DemoPartnerAccessTest {

    private static final int GRANTOR = 1;

    @Autowired private DemoPartnerAccessService demoPartnerAccessService;
    @Autowired private DemoPartnerAccessRepository demoPartnerAccessRepository;
    @Autowired private CsService csService;
    @Autowired private RetailerService retailerService;
    @Autowired private SessionFactory sessionFactory;

    @Test
    @Rollback
    public void grantAllowsPartnerWithoutTouchingPositionMapping() throws Exception {
        int salesUser = this.anySalesUser();
        int fofoId = this.anyActiveStoreNotMappedTo(salesUser);
        Assert.assertFalse(demoPartnerAccessService.isAllowed(salesUser, fofoId));

        Map<String, Object> result = demoPartnerAccessService.grant(GRANTOR, salesUser, Collections.singletonList(fofoId));
        this.session().flush();

        Assert.assertEquals(1, result.get("granted"));
        Assert.assertTrue(demoPartnerAccessService.isAllowed(salesUser, fofoId));
        Assert.assertTrue(demoPartnerAccessService.getDemoFofoIds(salesUser).contains(fofoId));
        List<Integer> positionFofoIds = csService.getAuthUserIdPartnerIdMapping().get(salesUser);
        Assert.assertTrue("demo partner must not leak into the position mapping",
                positionFofoIds == null || !positionFofoIds.contains(fofoId));

        CustomRetailer retailer = retailerService.getFofoRetailer(fofoId);
        Assert.assertTrue(demoPartnerAccessService.getDemoPartnerEmails(salesUser).contains(retailer.getEmail()));

        DemoPartnerAccess grant = demoPartnerAccessRepository.selectActive(salesUser, fofoId);
        demoPartnerAccessService.revoke(GRANTOR, grant.getId());
        this.session().flush();

        Assert.assertFalse(demoPartnerAccessService.isAllowed(salesUser, fofoId));
        Assert.assertNull(demoPartnerAccessRepository.selectActive(salesUser, fofoId));
    }

    @Test
    @Rollback
    public void grantSkipsDuplicateAndPositionMappedPartners() throws Exception {
        int salesUser = this.anySalesUser();
        int fofoId = this.anyActiveStoreNotMappedTo(salesUser);
        demoPartnerAccessService.grant(GRANTOR, salesUser, Collections.singletonList(fofoId));
        this.session().flush();

        List<Integer> positionFofoIds = csService.getAuthUserIdPartnerIdMapping().get(salesUser);
        List<Integer> request = positionFofoIds == null || positionFofoIds.isEmpty()
                ? Collections.singletonList(fofoId) : Arrays.asList(fofoId, positionFofoIds.get(0));
        Map<String, Object> result = demoPartnerAccessService.grant(GRANTOR, salesUser, request);

        Assert.assertEquals(0, result.get("granted"));
        Assert.assertEquals(request.size(), ((List<?>) result.get("skipped")).size());
    }

    @Test(expected = ProfitMandiBusinessException.class)
    @Rollback
    public void grantRejectsNonSalesUser() throws Exception {
        int nonSales = ((Number) this.session().createNativeQuery(
                "SELECT u.id FROM auth.auth_user u WHERE u.active = 1 AND u.id NOT IN "
                        + "(SELECT auth_user_id FROM cs.position WHERE category_id = 4) LIMIT 1").getSingleResult()).intValue();
        demoPartnerAccessService.grant(GRANTOR, nonSales, Collections.singletonList(this.anyActiveStoreNotMappedTo(nonSales)));
    }

    @Test
    @Rollback
    public void salesUserCannotManageGrants() {
        Assert.assertFalse(demoPartnerAccessService.canManage(this.anySalesUser()));
    }

    @Test
    @Rollback
    public void revokingTwiceFails() throws Exception {
        int salesUser = this.anySalesUser();
        int fofoId = this.anyActiveStoreNotMappedTo(salesUser);
        demoPartnerAccessService.grant(GRANTOR, salesUser, Collections.singletonList(fofoId));
        this.session().flush();
        int id = demoPartnerAccessRepository.selectActive(salesUser, fofoId).getId();
        demoPartnerAccessService.revoke(GRANTOR, id);
        this.session().flush();
        try {
            demoPartnerAccessService.revoke(GRANTOR, id);
            Assert.fail("second revoke must fail");
        } catch (ProfitMandiBusinessException expected) {
        }
    }

    // Active Sales user who cannot see every menu (no L5 position, not an all-menu email, not Business Intelligence).
    private int anySalesUser() {
        return ((Number) this.session().createNativeQuery(
                "SELECT p.auth_user_id FROM cs.position p JOIN auth.auth_user u ON u.id = p.auth_user_id "
                        + "WHERE p.category_id = 4 AND u.active = 1 AND u.email_id NOT IN (:emails) AND p.auth_user_id NOT IN "
                        + "(SELECT auth_user_id FROM cs.position WHERE escalation_type = 'L5' OR category_id = 19) "
                        + "ORDER BY p.auth_user_id LIMIT 1")
                .setParameter("emails", AdminUser.ALL_MENU_EMAILS).getSingleResult()).intValue();
    }

    private int anyActiveStoreNotMappedTo(int authUserId) throws Exception {
        List<Integer> mapped = csService.getAuthUserIdPartnerIdMapping().get(authUserId);
        List<?> ids = this.session().createNativeQuery(
                "SELECT fs.id FROM fofo.fofo_store fs WHERE fs.active = 1 AND fs.internal = 0 ORDER BY fs.id").getResultList();
        for (Object id : ids) {
            int fofoId = ((Number) id).intValue();
            if (mapped == null || !mapped.contains(fofoId)) {
                return fofoId;
            }
        }
        throw new IllegalStateException("No unmapped active store");
    }

    private Session session() {
        return sessionFactory.getCurrentSession();
    }
}