com.axelor.auth.service.PermissionAssistantService.java Source code

Java tutorial

Introduction

Here is the source code for com.axelor.auth.service.PermissionAssistantService.java

Source

/**
 * Axelor Business Solutions
 *
 * Copyright (C) 2015 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.axelor.auth.service;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import org.apache.commons.io.output.FileWriterWithEncoding;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;

import com.axelor.app.AppSettings;
import com.axelor.auth.db.Group;
import com.axelor.auth.db.IMessage;
import com.axelor.auth.db.Permission;
import com.axelor.auth.db.PermissionAssistant;
import com.axelor.auth.db.repo.GroupRepository;
import com.axelor.auth.db.repo.PermissionAssistantRepository;
import com.axelor.auth.db.repo.PermissionRepository;
import com.axelor.i18n.I18n;
import com.axelor.inject.Beans;
import com.axelor.meta.MetaFiles;
import com.axelor.meta.db.MetaField;
import com.axelor.meta.db.MetaFile;
import com.axelor.meta.db.MetaModel;
import com.axelor.meta.db.MetaPermission;
import com.axelor.meta.db.MetaPermissionRule;
import com.axelor.meta.db.repo.MetaModelRepository;
import com.axelor.meta.db.repo.MetaPermissionRepository;
import com.axelor.meta.db.repo.MetaPermissionRuleRepository;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;

public class PermissionAssistantService {

    private static final Logger LOG = LoggerFactory.getLogger(PermissionAssistantService.class);

    @Inject
    private MetaPermissionRepository metaPermissionRepository;

    @Inject
    private PermissionRepository permissionRepository;

    @Inject
    private MetaPermissionRuleRepository ruleRepository;

    @Inject
    private GroupRepository groupRepository;

    @Inject
    private MetaModelRepository modelRepository;

    private String errorLog = "";

    @SuppressWarnings("serial")
    private List<String> groupHeader = new ArrayList<String>() {
        {
            add("");
            add(I18n.get("Read"));
            add(I18n.get("Write"));
            add(I18n.get("Create"));
            add(I18n.get("Delete"));
            add(I18n.get("Export"));
            add(I18n.get("Readonly If"));
            add(I18n.get("Hide If"));
        }
    };

    private String getFileName(PermissionAssistant assistant) {

        String userCode = assistant.getCreatedBy().getCode();
        String dateString = LocalDateTime.now().toString("yyyyMMddHHmm");
        String fileName = userCode + "-" + dateString + ".csv";

        return fileName;
    }

    public void createFile(PermissionAssistant assistant) {

        AppSettings appSettings = AppSettings.get();
        File permFile = new File(appSettings.get("file.upload.dir"), getFileName(assistant));

        try {

            FileWriterWithEncoding fileWriter = new FileWriterWithEncoding(permFile, "utf-8");
            CSVWriter csvWriter = new CSVWriter(fileWriter, ';');
            writeGroup(csvWriter, assistant);
            csvWriter.close();

            createMetaFile(permFile, assistant);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Transactional
    public void createMetaFile(File permFile, PermissionAssistant assistant) {

        MetaFile metaFile = new MetaFile();
        metaFile.setFileName(permFile.getName());
        metaFile.setFilePath(permFile.getName());

        assistant.setMetaFile(metaFile);

        Beans.get(PermissionAssistantRepository.class).save(assistant);
    }

    private void writeGroup(CSVWriter csvWriter, PermissionAssistant assistant) {

        @SuppressWarnings("serial")
        List<String> headerRow = new ArrayList<String>() {
            {
                add("Object");
                add("Field");
                add("Title");
            }
        };

        String[] groupRow = new String[assistant.getGroupSet().size() * 8 + 3];
        Integer count = 3;
        for (Group group : assistant.getGroupSet()) {
            groupRow[count + 1] = group.getCode();
            headerRow.addAll(groupHeader);
            count += 8;
        }

        LOG.debug("Header row created: {}", headerRow);

        csvWriter.writeNext(groupRow);
        csvWriter.writeNext(headerRow.toArray(groupRow));

        writeObject(csvWriter, assistant, groupRow.length);

    }

    public Comparator<Object> compareField() {

        return new Comparator<Object>() {
            @Override
            public int compare(Object field1, Object field2) {
                return ((MetaField) field1).getName().compareTo(((MetaField) field2).getName());
            }
        };
    }

    private void writeObject(CSVWriter csvWriter, PermissionAssistant assistant, Integer size) {

        String language = assistant.getLanguage();
        language = language != null ? language : "en";

        LOG.debug("Language selected: {}", language);
        ResourceBundle bundle = I18n.getBundle(new Locale(language));

        for (MetaModel object : assistant.getObjectSet()) {

            String[] row = new String[size];
            row[0] = object.getFullName();
            csvWriter.writeNext(row);

            List<MetaField> fieldList = object.getMetaFields();
            Collections.sort(fieldList, compareField());

            for (MetaField field : fieldList) {

                row = new String[size];
                row[1] = field.getName();

                String title = field.getLabel();
                if (!Strings.isNullOrEmpty(title)) {
                    title = bundle.getString(title);
                }
                row[2] = title;

                csvWriter.writeNext(row);
            }
        }

    }

    private boolean checkHeaderRow(String[] headerRow) {

        @SuppressWarnings("serial")
        List<String> headerList = new ArrayList<String>() {
            {
                add("Object");
                add("Field");
                add("Title");
            }
        };

        Integer count = 3;
        while (count < headerRow.length) {
            headerList.addAll(groupHeader);
            count += 8;
        }
        LOG.debug("Standard Headers: {}", headerList);

        String[] headers = headerList.toArray(new String[headerList.size()]);
        LOG.debug("File Headers: {}", Arrays.asList(headerRow));

        return Arrays.equals(headers, headerRow);

    }

    public String importPermissions(PermissionAssistant permissionAssistant) {

        try {
            MetaFile metaFile = permissionAssistant.getMetaFile();
            File csvFile = MetaFiles.getPath(metaFile).toFile();
            CSVReader csvReader = new CSVReader(new FileReader(csvFile), ';');

            String[] groupRow = csvReader.readNext();
            if (groupRow == null || groupRow.length < 11) {
                errorLog = I18n.get(IMessage.BAD_FILE);
            }

            String[] headerRow = csvReader.readNext();
            if (headerRow == null) {
                errorLog = I18n.get(IMessage.NO_HEADER);
            }
            if (!checkHeaderRow(headerRow)) {
                errorLog = I18n.get(IMessage.BAD_HEADER) + Arrays.asList(headerRow);
            }

            if (!errorLog.equals("")) {
                csvReader.close();
                return errorLog;
            }

            Map<String, Group> groupMap = checkBadGroups(groupRow);
            Map<String, MetaPermission> metaPermissionDict = new HashMap<String, MetaPermission>();
            processCSV(csvReader, groupRow, null, metaPermissionDict, groupMap);

            saveGroups(groupMap);

        } catch (Exception e) {
            e.printStackTrace();
            errorLog += "\n" + String.format(I18n.get(IMessage.ERR_IMPORT_WITH_MSG), e.getMessage());
        }

        return errorLog;
    }

    @Transactional
    public void saveGroups(Map<String, Group> groupMap) {

        for (Group group : groupMap.values()) {
            groupRepository.save(group);
        }

    }

    private Map<String, Group> checkBadGroups(String[] groupRow) {

        List<String> badGroups = new ArrayList<String>();
        Map<String, Group> groupMap = new HashMap<String, Group>();

        for (Integer glen = 4; glen < groupRow.length; glen += 8) {

            String groupName = groupRow[glen];
            Group group = groupRepository.all().filter("self.code = ?1", groupName).fetchOne();
            if (group == null) {
                badGroups.add(groupName);
            } else {
                groupMap.put(groupName, group);
            }
        }

        if (!badGroups.isEmpty()) {
            errorLog += "\n" + String.format(I18n.get(IMessage.NO_GROUP), badGroups);
        }

        return groupMap;
    }

    private String checkObject(String objectName) {

        MetaModel model = modelRepository.all().filter("self.fullName = ?1", objectName).fetchOne();

        if (model == null) {
            errorLog += "\n" + String.format(I18n.get(IMessage.NO_OBJECT), objectName);
            return null;
        }

        return objectName;
    }

    private void processCSV(CSVReader csvReader, String[] groupRow,

            String objectName, Map<String, MetaPermission> metaPermissionDict, Map<String, Group> groupMap)
            throws IOException {

        String[] row = csvReader.readNext();

        if (row == null) {
            return;
        }

        for (Integer groupIndex = 4; groupIndex < row.length; groupIndex += 8) {

            String groupName = groupRow[groupIndex];
            if (!groupMap.containsKey(groupName)) {
                continue;
            }

            String[] rowGroup = (String[]) Arrays.copyOfRange(row, groupIndex, groupIndex + 8);

            if (!Strings.isNullOrEmpty(groupName) && !Strings.isNullOrEmpty(row[0])) {
                objectName = checkObject(row[0]);
                if (objectName == null) {
                    break;
                }
                metaPermissionDict.put(groupName, getMetaPermission(groupMap.get(groupName), objectName));
                updatePermission(groupMap.get(groupName), objectName, rowGroup);
            } else if (objectName != null && !Strings.isNullOrEmpty(row[1])) {
                updateFieldPermission(metaPermissionDict.get(groupName), row[1], rowGroup);
            }

        }

        processCSV(csvReader, groupRow, objectName, metaPermissionDict, groupMap);

    }

    public MetaPermission getMetaPermission(Group group, String objectName) {

        String[] objectNames = objectName.split("\\.");
        String groupName = group.getCode();
        String permName = groupName + "." + objectNames[objectNames.length - 1];
        MetaPermission metaPermission = metaPermissionRepository.all().filter("self.name = ?1", permName)
                .fetchOne();

        if (metaPermission == null) {
            LOG.debug("Create metaPermission group: {}, object: {}", groupName, objectName);

            metaPermission = new MetaPermission();
            metaPermission.setName(permName);
            metaPermission.setObject(objectName);

            group.addMetaPermission(metaPermission);

        }

        return metaPermission;
    }

    public MetaPermission updateFieldPermission(MetaPermission metaPermission, String field, String[] row) {

        MetaPermissionRule permissionRule = ruleRepository.all()
                .filter("self.field = ?1 and self.metaPermission.name = ?2", field, metaPermission.getName())
                .fetchOne();

        if (permissionRule == null) {
            permissionRule = new MetaPermissionRule();
            permissionRule.setMetaPermission(metaPermission);
            permissionRule.setField(field);
        }

        permissionRule.setCanRead(row[0].equalsIgnoreCase("x"));
        permissionRule.setCanWrite(row[1].equalsIgnoreCase("x"));
        permissionRule.setCanExport(row[4].equalsIgnoreCase("x"));
        permissionRule.setReadonlyIf(row[5]);
        permissionRule.setHideIf(row[6]);
        metaPermission.addRule(permissionRule);

        return metaPermission;
    }

    public void updatePermission(Group group, String objectName, String[] row) {

        String[] objectNames = objectName.split("\\.");
        String groupName = group.getCode();
        String permName = groupName + "." + objectNames[objectNames.length - 1];

        Permission permission = permissionRepository.all().filter("self.name = ?1", permName).fetchOne();
        boolean newPermission = false;

        if (permission == null) {
            newPermission = true;
            permission = new Permission();
            permission.setName(permName);
            permission.setObject(objectName);
        }

        permission.setCanRead(row[0].equalsIgnoreCase("x"));
        permission.setCanWrite(row[1].equalsIgnoreCase("x"));
        permission.setCanCreate(row[2].equalsIgnoreCase("x"));
        permission.setCanRemove(row[3].equalsIgnoreCase("x"));
        permission.setCanExport(row[4].equalsIgnoreCase("x"));

        if (newPermission) {
            group.addPermission(permission);
        }
    }
}