Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(exportExcel): Generate and save excel to file system, Download generated file with token #1477

Merged
merged 2 commits into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,12 @@ private void flattenlinkedReleaseOfRelease(Map<String, ReleaseRelationship> rele
}));
}

public void sendExportSpreadsheetSuccessMail(String url, String recepient) throws TException {
mailUtil.sendMail(recepient, MailConstants.SUBJECT_SPREADSHEET_EXPORT_SUCCESS,
MailConstants.TEXT_SPREADSHEET_EXPORT_SUCCESS, SW360Constants.NOTIFICATION_CLASS_PROJECT, "", false,
url);
}

private Map<String, String> createProjectCSRow(String relation, Project prj,
List<Map<String, String>> clearingStatusList) {
String projectId = prj.getId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class MailConstants {
public static final String SUBJECT_FOR_CLOSED_CLEARING_REQUEST = "subjectForClosedClearingRequest";
public static final String SUBJECT_FOR_REJECTED_CLEARING_REQUEST = "subjectForRejectedClearingRequest";
public static final String SUBJECT_FOR_UPDATED_PROJECT_WITH_CLEARING_REQUEST = "subjectForUpdatedProjectWithClearingRequest";
public static final String SUBJECT_SPREADSHEET_EXPORT_SUCCESS = "subjectForSuccessfulExport";

public static final String TEXT_FOR_NEW_MODERATION_REQUEST = "textForNewModerationRequest";
public static final String TEXT_FOR_UPDATE_MODERATION_REQUEST = "textForUpdateModerationRequest";
Expand All @@ -55,6 +56,7 @@ public class MailConstants {
public static final String TEXT_FOR_UPDATE_PROJECT = "textForUpdateProject";
public static final String TEXT_FOR_CLOSED_CLEARING_REQUEST = "textForClosedClearingRequest";
public static final String TEXT_FOR_REJECTED_CLEARING_REQUEST = "textForRejectedClearingRequest";
public static final String TEXT_SPREADSHEET_EXPORT_SUCCESS = "textForSuccessfulExport";

private MailConstants() {
// Utility class with only static functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class MailUtil extends BackendUtils {
private String enableSsl;
private String enableDebug;
private String supportMailAddress;
private String smtpSSLProtocol;

public MailUtil() {
mailExecutor = fixedThreadPoolWithQueueSize(MAIL_ASYNC_SEND_THREAD_LIMIT, MAIL_ASYNC_SEND_QUEUE_LIMIT);
Expand All @@ -96,6 +97,7 @@ private void setBasicProperties() {
password = loadedProperties.getProperty("MailUtil_password", "");
enableDebug = loadedProperties.getProperty("MailUtil_enableDebug", "false");
supportMailAddress = loadedProperties.getProperty("MailUtil_supportMailAddress","");
smtpSSLProtocol = loadedProperties.getProperty("MailUtil_smtpSSLProtocol", "");
}

private void setSession() {
Expand All @@ -111,6 +113,8 @@ private void setSession() {
properties.setProperty("mail.smtp.ssl.enable", enableSsl);

properties.setProperty("mail.debug", enableDebug);
properties.setProperty("mail.smtp.ssl.protocols", smtpSSLProtocol);


if (!"false".equals(isAuthenticationNecessary)) {
Authenticator auth = new SMTPAuthenticator(login, password);
Expand Down
4 changes: 4 additions & 0 deletions backend/src-common/src/main/resources/sw360.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ MailUtil_login=
MailUtil_password=
MailUtil_enableDebug=
MailUtil_supportMailAddress=
MailUtil_smtpSSLProtocol=

# text patterns for mail utility
defaultBegin = \
Expand Down Expand Up @@ -53,7 +54,9 @@ subjectForUpdatedClearingRequest= Your clearing request <%s> has been updated fo
subjectForClosedClearingRequest= Your clearing request <%s> has been closed for Project <%s>
subjectForRejectedClearingRequest= Your clearing request <%s> has been rejected for Project <%s>
subjectForUpdatedProjectWithClearingRequest= Project <%s> with clearing request <%s> updated
subjectForSuccessfulExport = Spreadsheet Export Successful

textForSuccessfulExport = The project spreadsheet export successfully completed. Please find the download link(%s) here.
textForNewModerationRequest= a new moderation request has been added to your SW360-account.\n\n
textForUpdateModerationRequest= \
one of the moderation requests previously added to your \
Expand All @@ -79,3 +82,4 @@ textForRejectedClearingRequest= your clearing request with id: %s for the projec
enable.sw360.change.log=false
sw360changelog.output.path=sw360changelog/sw360changelog
auto.set.ecc.status=false
send.project.spreadsheet.export.to.mail.enabled=false
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,9 @@ public Set<String> getGroups() throws TException {
public int getMyAccessibleProjectCounts(User user) throws TException {
return handler.getMyAccessibleProjects(user);
}

@Override
public void sendExportSpreadsheetSuccessMail(String url, String recepient) throws TException {
handler.sendExportSpreadsheetSuccessMail(url, recepient);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class PortalConstants {
public static final String CLEARING_REPORT_TEMPLATE_TO_FILENAMEMAPPING;
public static final String CLEARING_REPORT_TEMPLATE_FORMAT;
public static final String DISABLE_CLEARING_REQUEST_FOR_PROJECT_WITH_GROUPS;
public static final Boolean SEND_PROJECT_SPREADSHEET_EXPORT_TO_MAIL_ENABLED;
public static final String LOAD_OPEN_MODERATION_REQUEST = "loadOpenModerationRequest";
public static final String LOAD_CLOSED_MODERATION_REQUEST = "loadClosedModerationRequest";

Expand Down Expand Up @@ -592,6 +593,8 @@ public class PortalConstants {

// Excel export
public static final String EXPORT_TO_EXCEL = "export_to_excel";
public static final String EMAIL_EXPORTED_EXCEL = "email_exported_excel";
public static final String DOWNLOAD_EXCEL = "download_excel";
public static final String EXPORT_CLEARING_TO_EXCEL = "export_clearing_to_excel";
public static final String EXPORT_ID = "export_id";

Expand Down Expand Up @@ -695,6 +698,7 @@ public class PortalConstants {
IS_COMPONENT_VISIBILITY_RESTRICTION_ENABLED = Boolean.parseBoolean(
System.getProperty("RunComponentVisibilityRestrictionTest", props.getProperty("component.visibility.restriction.enabled", "false")));
DISABLE_CLEARING_REQUEST_FOR_PROJECT_WITH_GROUPS = props.getProperty("org.eclipse.sw360.disable.clearing.request.for.project.group", "");
SEND_PROJECT_SPREADSHEET_EXPORT_TO_MAIL_ENABLED = Boolean.parseBoolean(props.getProperty("send.project.spreadsheet.export.to.mail.enabled", "false"));
}

private PortalConstants() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,12 @@ public void serveResource(ResourceRequest request, ResourceResponse response) th
updateVulnerabilitiesProject(request, response);
} else if (PortalConstants.UPDATE_VULNERABILITY_RATINGS.equals(action)) {
updateVulnerabilityRating(request, response);
} else if (PortalConstants.EMAIL_EXPORTED_EXCEL.equals(action)) {
exportExcelWithEmail(request, response);
} else if (PortalConstants.EXPORT_TO_EXCEL.equals(action)) {
exportExcel(request, response);
} else if (PortalConstants.DOWNLOAD_EXCEL.equals(action)) {
downloadExcel(request, response);
} else if (PortalConstants.EXPORT_CLEARING_TO_EXCEL.equals(action)) {
exportReleasesSpreadsheet(request, response);
} else if (PortalConstants.DOWNLOAD_LICENSE_INFO.equals(action)) {
Expand Down Expand Up @@ -290,6 +294,25 @@ else if ((PortalConstants.LOAD_OBLIGATIONS_EDIT.equals(action)
}
}

private void downloadExcel(ResourceRequest request, ResourceResponse response) {
final User user = UserCacheHolder.getUserFromRequest(request);
final String token = request.getParameter("token");
String filename = null;

try {
boolean extendedByReleases = Boolean.valueOf(request.getParameter(PortalConstants.EXTENDED_EXCEL_EXPORT));
ProjectExporter exporter = new ProjectExporter(thriftClients.makeComponentClient(),
thriftClients.makeProjectClient(), user, extendedByReleases);
filename = String.format("projects-%s.xlsx", SW360Utils.getCreatedOn());
PortletResponseUtil.sendFile(request, response, filename, exporter.downloadExcelSheet(token),
CONTENT_TYPE_OPENXML_SPREADSHEET);
} catch (IOException | TException e) {
log.error("An error occurred while generating the Excel export", e);
response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
}
}

private void serveViewVendor(ResourceRequest request, ResourceResponse response) throws IOException, PortletException {
String what = request.getParameter(PortalConstants.WHAT);
String where = request.getParameter(PortalConstants.WHERE);
Expand Down Expand Up @@ -1027,20 +1050,93 @@ private void exportExcel(ResourceRequest request, ResourceResponse response) {
String filename = String.format("projects-%s.xlsx", SW360Utils.getCreatedOn());
try {
boolean extendedByReleases = Boolean.valueOf(request.getParameter(PortalConstants.EXTENDED_EXCEL_EXPORT));
List<Project> projects = getFilteredProjectList(request);
ProjectService.Iface client = thriftClients.makeProjectClient();
int total = client.getMyAccessibleProjectCounts(user);
PaginationData pageData = new PaginationData();
pageData.setAscending(true);
Map<PaginationData, List<Project>> pageDtToProjects;
Set<Project> projects = new HashSet<>();
int displayStart = 0;
int rowsPerPage = 500;
while (0 < total) {
pageData.setDisplayStart(displayStart);
pageData.setRowsPerPage(rowsPerPage);
displayStart = displayStart + rowsPerPage;
pageDtToProjects = client.getAccessibleProjectsSummaryWithPagination(user, pageData);
projects.addAll(pageDtToProjects.entrySet().iterator().next().getValue());
total = total - rowsPerPage;
}

List<Project> listOfProjects = new ArrayList<Project>(projects);
if (!isNullOrEmpty(projectId)) {
Project project = projects.stream().filter(p -> p.getId().equals(projectId)).findFirst().get();
Project project = listOfProjects.stream().filter(p -> p.getId().equals(projectId)).findFirst().get();
fillVendor(project);
filename = String.format("project-%s-%s-%s.xlsx", project.getName(), project.getVersion(), SW360Utils.getCreatedOn());
}
ProjectExporter exporter = new ProjectExporter(
thriftClients.makeComponentClient(),
thriftClients.makeProjectClient(),
user,
projects,
listOfProjects,
extendedByReleases);
PortletResponseUtil.sendFile(request, response, filename, exporter.makeExcelExport(projects), CONTENT_TYPE_OPENXML_SPREADSHEET);
} catch (IOException | SW360Exception e) {
PortletResponseUtil.sendFile(request, response, filename, exporter.makeExcelExport(listOfProjects), CONTENT_TYPE_OPENXML_SPREADSHEET);
} catch (IOException | TException e) {
log.error("An error occurred while generating the Excel export", e);
response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
}
}

private void exportExcelWithEmail(ResourceRequest request, ResourceResponse response) {
final User user = UserCacheHolder.getUserFromRequest(request);
final String projectId = request.getParameter(Project._Fields.ID.toString());
ResourceBundle resourceBundle = ResourceBundleUtil.getBundle("content.Language", request.getLocale(), getClass());
String token = null;

try {
setSessionMessage(request, LanguageUtil.get(resourceBundle,"excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed"));
ProjectService.Iface client = thriftClients.makeProjectClient();
boolean extendedByReleases = Boolean.valueOf(request.getParameter(PortalConstants.EXTENDED_EXCEL_EXPORT));
int total = client.getMyAccessibleProjectCounts(user);
PaginationData pageData = new PaginationData();
pageData.setAscending(true);
Map<PaginationData, List<Project>> pageDtToProjects;
Set<Project> projects = new HashSet<>();
int displayStart = 0;
int rowsPerPage = 500;
while (0 < total) {
pageData.setDisplayStart(displayStart);
pageData.setRowsPerPage(rowsPerPage);
displayStart = displayStart + rowsPerPage;
pageDtToProjects = client.getAccessibleProjectsSummaryWithPagination(user, pageData);
projects.addAll(pageDtToProjects.entrySet().iterator().next().getValue());
total = total - rowsPerPage;
}

List<Project> listOfProjects = new ArrayList<Project>(projects);
if (!isNullOrEmpty(projectId)) {
Project project = listOfProjects.stream().filter(p -> p.getId().equals(projectId)).findFirst().get();
fillVendor(project);
}
ProjectExporter exporter = new ProjectExporter(thriftClients.makeComponentClient(),
thriftClients.makeProjectClient(), user, listOfProjects, extendedByReleases);

token = exporter.makeExcelExportForProject(listOfProjects, user);

String portletId = (String) request.getAttribute(WebKeys.PORTLET_ID);
ThemeDisplay tD = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
long plid = tD.getPlid();

LiferayPortletURL projectUrl = PortletURLFactoryUtil.create(request, portletId, plid,
PortletRequest.RESOURCE_PHASE);
projectUrl.setParameter("action", PortalConstants.DOWNLOAD_EXCEL);
projectUrl.setParameter("token", token);
projectUrl.setParameter(PortalConstants.EXTENDED_EXCEL_EXPORT, String.valueOf(extendedByReleases));

if(!CommonUtils.isNullEmptyOrWhitespace(token)) {
client.sendExportSpreadsheetSuccessMail(projectUrl.toString(), user.getEmail());
}
} catch (IOException | TException | PortletException e) {
log.error("An error occurred while generating the Excel export", e);
response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
<portlet:param name="<%=PortalConstants.ACTION%>" value='<%=PortalConstants.LOAD_PROJECT_LIST%>'/>
</portlet:resourceURL>

<portlet:resourceURL var="generateExcelReport">
<portlet:param name="<%=PortalConstants.ACTION%>" value="<%=PortalConstants.EMAIL_EXPORTED_EXCEL%>"/>
<portlet:param name="<%=PortalConstants.PROJECT_ID%>" value="${docid}"/>
</portlet:resourceURL>

<div class="container" style="display: none;">
<div class="row">
<div class="col-3 sidebar">
Expand Down Expand Up @@ -530,17 +535,29 @@

// Export Spreadsheet action
function exportSpreadsheet(type) {
var portletURL = PortletURL.createURL('<%= PortletURLFactoryUtil.create(request, portletDisplay.getId(), themeDisplay.getPlid(), PortletRequest.RESOURCE_PHASE) %>')
var isEMailEnabled = <%=PortalConstants.SEND_PROJECT_SPREADSHEET_EXPORT_TO_MAIL_ENABLED%>;
if(isEMailEnabled){
var isWithReleases = (type === 'projectWithReleases' ? 'true' : 'false');
$.ajax({
type: 'POST',
url: '<%=generateExcelReport%>',
cache: false,
data: {
"<portlet:namespace/><%=PortalConstants.EXTENDED_EXCEL_EXPORT%>": isWithReleases,
}
});
} else {
var portletURL = PortletURL.createURL('<%= PortletURLFactoryUtil.create(request, portletDisplay.getId(), themeDisplay.getPlid(), PortletRequest.RESOURCE_PHASE) %>')
.setParameter('<%=PortalConstants.ACTION%>', '<%=PortalConstants.EXPORT_TO_EXCEL%>');
portletURL.setParameter('<%=Project._Fields.NAME%>', $('#project_name').val());
portletURL.setParameter('<%=Project._Fields.TYPE%>', $('#project_type').val());
portletURL.setParameter('<%=Project._Fields.PROJECT_RESPONSIBLE%>', $('#project_responsible').val());
portletURL.setParameter('<%=Project._Fields.BUSINESS_UNIT%>', $('#group').val());
portletURL.setParameter('<%=Project._Fields.STATE%>', $('#project_state').val());
portletURL.setParameter('<%=Project._Fields.TAG%>', $('#tag').val());
portletURL.setParameter('<%=PortalConstants.EXTENDED_EXCEL_EXPORT%>', type === 'projectWithReleases' ? 'true' : 'false');

window.location.href = portletURL.toString();
portletURL.setParameter('<%=Project._Fields.NAME%>', $('#project_name').val());
portletURL.setParameter('<%=Project._Fields.TYPE%>', $('#project_type').val());
portletURL.setParameter('<%=Project._Fields.PROJECT_RESPONSIBLE%>', $('#project_responsible').val());
portletURL.setParameter('<%=Project._Fields.BUSINESS_UNIT%>', $('#group').val());
portletURL.setParameter('<%=Project._Fields.STATE%>', $('#project_state').val());
portletURL.setParameter('<%=Project._Fields.TAG%>', $('#tag').val());
portletURL.setParameter('<%=PortalConstants.EXTENDED_EXCEL_EXPORT%>', type === 'projectWithReleases' ? 'true' : 'false');
window.location.href = portletURL.toString();
}
}

// delete action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,7 @@ import.obligation.element=Import Obligation Element
input=Input
an.obligation.with.the.same.name.already.exists=An Obligation with the same name already exists.
obligation.change.log.is.unavailable.because.obligation.does.not.exist=Obligation Change Log is unavailable because Obligation does not exist.
excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed=Excel report generation has started. We will send you an email with download link once completed.
## Refer to http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/ and add your datatables language

datatables.lang=https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/English.json
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,8 @@ list.of.licenses.were.imported=インポート成功ライセンス一覧:
index=No.
importing.process.is.already.running.please.try.again.later=インポートプロセスはすでに実行されています。 後でもう一度やり直してください。
obligation.change.log.is.unavailable.because.obligation.does.not.exist=オブリゲーションが存在しないため、オブリゲーションのチェンジログは取得できません。
excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed=Excel report generation has started. We will send you an email with download link once completed.

## Refer to http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/ and add your datatables language

datatables.lang=https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,7 @@ import.obligation.element=Nhập nghĩa vụ thành phần
input=Nhập
an.obligation.with.the.same.name.already.exists=Nghĩa vụ có cùng tên đã tồn tại.
obligation.change.log.is.unavailable.because.obligation.does.not.exist=Không xem được lịch sử thay đổi vì Obligation này không tồn tại.
excel.report.generation.has.started.we.will.send.you.an.email.with.download.link.once.completed=Excel report generation has started. We will send you an email with download link once completed.
## Refer to http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/ and add your datatables language

datatables.lang=https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Vietnamese.json
Loading