<repo_name>AndreyVMarkelov/delete-all-attachments<file_sep>/src/main/java/ru/andreymarkelov/atlas/plugins/attrrem/action/DeleteAttachAction.java
package ru.andreymarkelov.atlas.plugins.attrrem.action;

import java.util.Collection;

import com.atlassian.jira.bc.JiraServiceContext;
import com.atlassian.jira.bc.JiraServiceContextImpl;
import com.atlassian.jira.bc.issue.attachment.AttachmentService;
import com.atlassian.jira.config.SubTaskManager;
import com.atlassian.jira.exception.RemoveException;
import com.atlassian.jira.issue.AttachmentManager;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.attachment.Attachment;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.security.PermissionManager;
import com.atlassian.jira.security.xsrf.RequiresXsrfCheck;
import com.atlassian.jira.web.action.issue.AbstractViewIssue;
import ru.andreymarkelov.atlas.plugins.attrrem.manager.AttacherMgr;

import static com.atlassian.jira.permission.ProjectPermissions.DELETE_ALL_ATTACHMENTS;

public class DeleteAttachAction extends AbstractViewIssue {
    private static final long serialVersionUID = 2431906489689708128L;

    private final AttacherMgr attacherMgr;
    private final JiraAuthenticationContext authenticationContext;
    private final PermissionManager permissionManager;
    private final AttachmentService attachmentService;
    private final AttachmentManager attachmentManager;

    public DeleteAttachAction(
            SubTaskManager subTaskManager,
            AttacherMgr attacherMgr,
            JiraAuthenticationContext authenticationContext,
            PermissionManager permissionManager,
            AttachmentService attachmentService,
            AttachmentManager attachmentManager) {
        super(subTaskManager);
        this.attacherMgr = attacherMgr;
        this.authenticationContext = authenticationContext;
        this.permissionManager = permissionManager;
        this.attachmentService = attachmentService;
        this.attachmentManager = attachmentManager;
    }

    @Override
    @RequiresXsrfCheck
    protected String doExecute() {
        MutableIssue issue = this.getMutableIssue();
        if (!hasPermission(issue.getProjectObject())) {
            addErrorMessage(authenticationContext.getI18nHelper().getText("ru.andreymarkelov.atlas.plugins.attrrem.action.error.permission"));
            return ERROR;
        }

        JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(authenticationContext.getLoggedInUser());
        Collection<Attachment> attachments = issue.getAttachments();
        for (Attachment attachment : attachments) {
            try {
                attachmentService.delete(jiraServiceContext, attachment.getId());
                attachmentManager.deleteAttachment(attachment);
            } catch (RemoveException e) {
                addErrorMessage(authenticationContext.getI18nHelper().getText("ru.andreymarkelov.atlas.plugins.attrrem.action.error.file", attachment.getFilename()));
                return ERROR;
            }
        }
        return redirect();
    }

    private boolean hasPermission(Project project) {
        if (attacherMgr.isActiveForAll()) {
            return true;
        }

        if (project != null) {
            String[] projectKeys = attacherMgr.getProjectKeys();
            if (projectKeys != null) {
                for (String projectKey : projectKeys) {
                    if (projectKey.equals(project.getId().toString())) {
                        return permissionManager.hasPermission(DELETE_ALL_ATTACHMENTS, getIssueObject(), getLoggedInUser());
                    }
                }
            }
        }
        return false;
    }

    private String redirect() {
        return isInlineDialogMode() ? returnComplete() : getRedirect("/browse/" + getIssue().getString("key"));
    }
}
<file_sep>/src/main/resources/ru/andreymarkelov/atlas/plugins/attrrem/i18n/attachdeleter.properties
ru.andreymarkelov.atlas.plugins.attrrem.section=Delete All Attachments
ru.andreymarkelov.atlas.plugins.attrrem.settings.title=Delete All Attachments Settings
ru.andreymarkelov.atlas.plugins.attrrem.settings.desc=On this page you can configure projects when Delete All Attachments will be available.
ru.andreymarkelov.atlas.plugins.attrrem.settings.selectprojects=Projects
ru.andreymarkelov.atlas.plugins.attrrem.settings.selectprojects.desc=Choose projects where delete all attachments action will be available.
ru.andreymarkelov.atlas.plugins.attrrem.settings.allprojects=All Projects
ru.andreymarkelov.atlas.plugins.attrrem.settings.allprojects.desc=Choose if you want for all projects.
ru.andreymarkelov.atlas.plugins.attrrem.settings.save=Save
ru.andreymarkelov.atlas.plugins.attrrem.settings.success.text=Data was stored successfully.
ru.andreymarkelov.atlas.plugins.attrrem.action=Delete All Attachments
ru.andreymarkelov.atlas.plugins.attrrem.action.desc=Delete all issue attachements if you have permission.
ru.andreymarkelov.atlas.plugins.attrrem.action.confirm=Are you sure that you want to delete all attachments?
ru.andreymarkelov.atlas.plugins.attrrem.action.error=Error deleting all attachments
ru.andreymarkelov.atlas.plugins.attrrem.action.error.file=Error during deleting attachment "{0}"
ru.andreymarkelov.atlas.plugins.attrrem.action.error.permission=There are no permissions to delete all attachments. Please, contact to administrators.
ru.andreymarkelov.atlas.plugins.attrrem.postfunction.attachdelete.name=Delete All Attachments
ru.andreymarkelov.atlas.plugins.attrrem.postfunction.attachdelete.desc=This function deletes all attachments if an executor has permissions.
<file_sep>/src/main/java/ru/andreymarkelov/atlas/plugins/attrrem/workflow/function/DeleteAttachmentsFunctionFactory.java
package ru.andreymarkelov.atlas.plugins.attrrem.workflow.function;

import java.util.Collections;
import java.util.Map;

import com.atlassian.jira.plugin.workflow.AbstractWorkflowPluginFactory;
import com.atlassian.jira.plugin.workflow.WorkflowPluginFunctionFactory;
import com.opensymphony.workflow.loader.AbstractDescriptor;

public class DeleteAttachmentsFunctionFactory extends AbstractWorkflowPluginFactory implements WorkflowPluginFunctionFactory {
    @Override
    public Map<String, ?> getDescriptorParams(Map<String, Object> descriptorParams) {
        return Collections.emptyMap();
    }

    @Override
    protected void getVelocityParamsForEdit(Map<String, Object> velocityParams, AbstractDescriptor descriptor) {
    }

    @Override
    protected void getVelocityParamsForInput(Map<String, Object> velocityParams) {
    }

    @Override
    protected void getVelocityParamsForView(Map<String, Object> velocityParams, AbstractDescriptor descriptor) {
    }
}
<file_sep>/src/main/java/ru/andreymarkelov/atlas/plugins/attrrem/condition/AttachDeleterCondition.java
package ru.andreymarkelov.atlas.plugins.attrrem.condition;

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.plugin.webfragment.conditions.AbstractIssueWebCondition;
import com.atlassian.jira.plugin.webfragment.model.JiraHelper;
import com.atlassian.jira.security.PermissionManager;
import com.atlassian.jira.user.ApplicationUser;
import ru.andreymarkelov.atlas.plugins.attrrem.manager.AttacherMgr;

import static com.atlassian.jira.permission.ProjectPermissions.DELETE_ALL_ATTACHMENTS;

public class AttachDeleterCondition extends AbstractIssueWebCondition {
    private final AttacherMgr attacherMgr;
    private final PermissionManager permissionManager;

    public AttachDeleterCondition(PermissionManager permissionManager, AttacherMgr attacherMgr) {
        this.permissionManager = permissionManager;
        this.attacherMgr = attacherMgr;
    }

    public boolean shouldDisplay(ApplicationUser user, Issue issue, JiraHelper jiraHelper) {
        if (attacherMgr.isActiveForAll()) {
            return true;
        }

        if (issue != null && issue.getKey() != null) {
            String[] projectKeys = attacherMgr.getProjectKeys();
            if (projectKeys != null) {
                for (String projectKey : projectKeys) {
                    if (projectKey.equals(issue.getProjectObject().getId().toString())) {
                        return permissionManager.hasPermission(DELETE_ALL_ATTACHMENTS, issue, user);
                    }
                }
            }
        }
        return false;
    }
}
<file_sep>/README.md
# Delete All Attachments

Multiple Attachment Delete for Jira.
<file_sep>/src/main/resources/ru/andreymarkelov/atlas/plugins/attrrem/js/attach-deleter.js
AJS.$(function($) {
    var initDialogTriggers = function(context) {
        AJS.$(".issueaction-delete-all-attachments", context || document.body).each(function() {
            new JIRA.FormDialog({
                trigger: this,
                id: this.id + '-dialog',
                ajaxOptions: {
                    url: this.href,
                    data: { decorator: 'dialog', inline: 'true' }
                }
            });
        });
    };
    JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function (event, context, reason) {
        initDialogTriggers(context);
    });
    initDialogTriggers();
});
<file_sep>/src/main/java/ru/andreymarkelov/atlas/plugins/attrrem/action/AttachDeleterConfig.java
package ru.andreymarkelov.atlas.plugins.attrrem.action;

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

import com.atlassian.jira.permission.GlobalPermissionKey;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.jira.security.GlobalPermissionManager;
import com.atlassian.jira.security.xsrf.RequiresXsrfCheck;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.web.action.JiraWebActionSupport;
import ru.andreymarkelov.atlas.plugins.attrrem.manager.AttacherMgr;

public class AttachDeleterConfig extends JiraWebActionSupport {
    private static final long serialVersionUID = -8881690781888724545L;

    private final AttacherMgr attacherMgr;
    private final ProjectManager projectManager;
    private final GlobalPermissionManager globalPermissionManager;

    private boolean isSaved = false;
    private List<String> savedProjKeys;
    private String[] selectedProjKeys;
    private boolean forAllProjects;

    public AttachDeleterConfig(
            AttacherMgr attacherMgr,
            ProjectManager projectManager,
            GlobalPermissionManager globalPermissionManager) {
        this.attacherMgr = attacherMgr;
        this.projectManager = projectManager;
        this.globalPermissionManager = globalPermissionManager;
    }

    @Override
    public String doDefault() {
        if(!hasAdminPermission()) {
            return PERMISSION_VIOLATION_RESULT;
        }

        this.forAllProjects = attacherMgr.isActiveForAll();
        this.selectedProjKeys = attacherMgr.getProjectKeys();
        this.savedProjKeys = selectedProjKeys == null ? null : Arrays.asList(selectedProjKeys);

        return INPUT;
    }

    @Override
    @RequiresXsrfCheck
    protected String doExecute() {
        if(!hasAdminPermission()) {
            return PERMISSION_VIOLATION_RESULT;
        }

        attacherMgr.setActiveForAll(forAllProjects);
        attacherMgr.setProjectKeys(selectedProjKeys);
        if (selectedProjKeys != null) {
            savedProjKeys = Arrays.asList(attacherMgr.getProjectKeys());
        }
        setSaved(true);
        return getRedirect("AttachDeleterConfig!default.jspa?saved=true");
    }

    public Map<String, String> getAllProjects() {
        Map<String, String> allProjs = new TreeMap<String, String>();
        List<Project> projects = projectManager.getProjectObjects();
        if (projects != null) {
            for (Project project : projects) {
                allProjs.put(project.getId().toString(), getProjView(project.getKey(), project.getName()));
            }
        }
        return allProjs;
    }

    private String getProjView(String key, String name) {
        return (key + ": " + name);
    }

    public List<String> getSavedProjKeys() {
        return savedProjKeys;
    }

    public String[] getSelectedProjKeys() {
        return selectedProjKeys;
    }

    public boolean hasAdminPermission() {
        ApplicationUser user = getLoggedInUser();
        if (user == null) {
            return false;
        }
        return globalPermissionManager.hasPermission(GlobalPermissionKey.ADMINISTER, user);
    }

    public boolean isSaved() {
        return isSaved;
    }

    public void setSaved(boolean isSaved) {
        this.isSaved = isSaved;
    }

    public void setSavedProjKeys(List<String> savedProjKeys) {
        this.savedProjKeys = savedProjKeys;
    }

    public void setSelectedProjKeys(String[] selectedProjKeys) {
        this.selectedProjKeys = selectedProjKeys;
    }

    public boolean isForAllProjects() {
        return forAllProjects;
    }

    public void setForAllProjects(boolean forAllProjects) {
        this.forAllProjects = forAllProjects;
    }
}
<file_sep>/src/main/resources/ru/andreymarkelov/atlas/plugins/attrrem/js/admin-attach-deleter.js
AJS.toInit(function () {

});
