mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
CE-1068: checkpoint commit of SES support
This commit is contained in:
@ -173,6 +173,19 @@
|
||||
<version>1.12.321</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-ses</artifactId>
|
||||
<version>1.12.705</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cloud.localstack</groupId>
|
||||
<artifactId>localstack-utils</artifactId>
|
||||
<version>0.2.20</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
|
@ -30,7 +30,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.storage.StorageInput;
|
||||
|
||||
/*******************************************************************************
|
||||
** Interface for actions that a backend can perform, based on streaming data
|
||||
** into the backend's storage.
|
||||
** into the backend's storage.
|
||||
*******************************************************************************/
|
||||
public interface QStorageInterface
|
||||
{
|
||||
@ -46,4 +46,15 @@ public interface QStorageInterface
|
||||
*******************************************************************************/
|
||||
InputStream getInputStream(StorageInput storageInput) throws QException;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
default void makePublic(StorageInput storageInput) throws QException
|
||||
{
|
||||
//////////
|
||||
// noop //
|
||||
//////////
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -93,4 +93,16 @@ public class StorageAction
|
||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(backend);
|
||||
return (qModule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void makePublic(StorageInput storageInput) throws QException
|
||||
{
|
||||
QBackendModuleInterface qBackendModuleInterface = preAction(storageInput);
|
||||
QStorageInterface storageInterface = qBackendModuleInterface.getStorageInterface();
|
||||
storageInterface.makePublic(storageInput);
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public class SendEmailAction
|
||||
addRecipient(emailMessage, to);
|
||||
}
|
||||
|
||||
Party from = sendMessageInput.getTo();
|
||||
Party from = sendMessageInput.getFrom();
|
||||
if(from instanceof MultiParty fromMultiParty)
|
||||
{
|
||||
for(Party party : fromMultiParty.getPartyList())
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.model.metadata.messaging.ses;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.SendMessageInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.SendMessageOutput;
|
||||
import com.kingsrook.qqq.backend.core.modules.messaging.MessagingProviderInterface;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class SESMessagingProvider implements MessagingProviderInterface
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public String getType()
|
||||
{
|
||||
return (SESMessagingProviderMetaData.TYPE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public SendMessageOutput sendMessage(SendMessageInput sendMessageInput) throws QException
|
||||
{
|
||||
return new SendSESAction().sendMessage(sendMessageInput);
|
||||
}
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.model.metadata.messaging.ses;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.messaging.QMessagingProviderMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.messaging.QMessagingProviderDispatcher;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class SESMessagingProviderMetaData extends QMessagingProviderMetaData
|
||||
{
|
||||
private String accessKey;
|
||||
private String secretKey;
|
||||
private String region;
|
||||
|
||||
public static final String TYPE = "SES";
|
||||
|
||||
static
|
||||
{
|
||||
QMessagingProviderDispatcher.registerMessagingProvider(new SESMessagingProvider());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public SESMessagingProviderMetaData()
|
||||
{
|
||||
super();
|
||||
setType(TYPE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for accessKey
|
||||
*******************************************************************************/
|
||||
public String getAccessKey()
|
||||
{
|
||||
return (this.accessKey);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for accessKey
|
||||
*******************************************************************************/
|
||||
public void setAccessKey(String accessKey)
|
||||
{
|
||||
this.accessKey = accessKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for accessKey
|
||||
*******************************************************************************/
|
||||
public SESMessagingProviderMetaData withAccessKey(String accessKey)
|
||||
{
|
||||
this.accessKey = accessKey;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for secretKey
|
||||
*******************************************************************************/
|
||||
public String getSecretKey()
|
||||
{
|
||||
return (this.secretKey);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for secretKey
|
||||
*******************************************************************************/
|
||||
public void setSecretKey(String secretKey)
|
||||
{
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for secretKey
|
||||
*******************************************************************************/
|
||||
public SESMessagingProviderMetaData withSecretKey(String secretKey)
|
||||
{
|
||||
this.secretKey = secretKey;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for region
|
||||
*******************************************************************************/
|
||||
public String getRegion()
|
||||
{
|
||||
return (this.region);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for region
|
||||
*******************************************************************************/
|
||||
public void setRegion(String region)
|
||||
{
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for region
|
||||
*******************************************************************************/
|
||||
public SESMessagingProviderMetaData withRegion(String region)
|
||||
{
|
||||
this.region = region;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.model.metadata.messaging.ses;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
|
||||
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
|
||||
import com.amazonaws.services.simpleemail.model.Body;
|
||||
import com.amazonaws.services.simpleemail.model.Content;
|
||||
import com.amazonaws.services.simpleemail.model.Destination;
|
||||
import com.amazonaws.services.simpleemail.model.Message;
|
||||
import com.amazonaws.services.simpleemail.model.SendEmailRequest;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.MultiParty;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.Party;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.PartyRole;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.SendMessageInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.SendMessageOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.email.EmailContentRole;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.email.EmailPartyRole;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class SendSESAction
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(SendSESAction.class);
|
||||
|
||||
private AmazonSimpleEmailService amazonSES;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public SendMessageOutput sendMessage(SendMessageInput sendMessageInput) throws QException
|
||||
{
|
||||
try
|
||||
{
|
||||
AmazonSimpleEmailService client = getAmazonSES(sendMessageInput);
|
||||
|
||||
///////////////////////////////////
|
||||
// build up a send email request //
|
||||
///////////////////////////////////
|
||||
SendEmailRequest request = new SendEmailRequest()
|
||||
.withSource(getSource(sendMessageInput))
|
||||
.withReplyToAddresses(getReplyTos(sendMessageInput))
|
||||
.withDestination(buildDestination(sendMessageInput))
|
||||
.withMessage(buildMessage(sendMessageInput));
|
||||
|
||||
client.sendEmail(request);
|
||||
LOG.info("SES Message [" + request.getMessage().getSubject().getData() + "] was sent to [" + request.getDestination().toString() + "].");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
String message = "An unexpected error occurred sending an SES message.";
|
||||
throw (new QException(message, e));
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
Message buildMessage(SendMessageInput input) throws QException
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// iterate over all contents of our input, looking for an HTML and Text version of the email //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Body body = new Body();
|
||||
for(com.kingsrook.qqq.backend.core.model.actions.messaging.Content content : CollectionUtils.nonNullList(input.getContentList()))
|
||||
{
|
||||
if(EmailContentRole.TEXT.equals(content.getContentRole()))
|
||||
{
|
||||
body.setText(new Content().withCharset("UTF-8").withData(content.getBody()));
|
||||
}
|
||||
else if(EmailContentRole.HTML.equals(content.getContentRole()))
|
||||
{
|
||||
body.setHtml(new Content().withCharset("UTF-8").withData(content.getBody()));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// error if no text or html body was provided //
|
||||
////////////////////////////////////////////////
|
||||
if(body.getText() == null && body.getHtml() == null)
|
||||
{
|
||||
throw (new QException("Cannot send SES message because neither a 'Text' nor an 'HTML' body was provided."));
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// warning if no subject was provided //
|
||||
////////////////////////////////////////
|
||||
Message message = new Message();
|
||||
message.setBody(body);
|
||||
|
||||
/////////////////////////////////////
|
||||
// warn if no subject was provided //
|
||||
/////////////////////////////////////
|
||||
if(input.getSubject() == null)
|
||||
{
|
||||
LOG.warn("Sending SES message with no subject.");
|
||||
}
|
||||
else
|
||||
{
|
||||
message.setSubject(new Content().withCharset("UTF-8").withData(input.getSubject()));
|
||||
}
|
||||
|
||||
return (message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
List<String> getReplyTos(SendMessageInput input) throws QException
|
||||
{
|
||||
////////////////////////////
|
||||
// no input, no reply tos //
|
||||
////////////////////////////
|
||||
if(input == null)
|
||||
{
|
||||
return (Collections.emptyList());
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// build up a list of froms if multi //
|
||||
///////////////////////////////////////
|
||||
List<Party> partyList = getPartyListFromParty(input.getFrom());
|
||||
if(partyList == null)
|
||||
{
|
||||
return (Collections.emptyList());
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// only get reply to parties //
|
||||
///////////////////////////////
|
||||
List<Party> replyToParties = partyList.stream().filter(p -> EmailPartyRole.REPLY_TO.equals(p.getRole())).toList();
|
||||
|
||||
//////////////////////////////////
|
||||
// get addresses from reply tos //
|
||||
//////////////////////////////////
|
||||
List<String> replyTos = replyToParties.stream().map(Party::getAddress).toList();
|
||||
|
||||
/////////////////////////////
|
||||
// return the from address //
|
||||
/////////////////////////////
|
||||
return (replyTos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
String getSource(SendMessageInput input) throws QException
|
||||
{
|
||||
///////////////////////////////
|
||||
// error if no from provided //
|
||||
///////////////////////////////
|
||||
if(input.getFrom() == null)
|
||||
{
|
||||
throw (new QException("Cannot send SES message because a FROM was not provided."));
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// build up a list of froms if multi //
|
||||
///////////////////////////////////////
|
||||
List<Party> partyList = getPartyListFromParty(input.getFrom());
|
||||
|
||||
///////////////////////////////////////
|
||||
// remove any roles that aren't FROM //
|
||||
///////////////////////////////////////
|
||||
partyList.removeIf(p -> p.getRole() != null && !EmailPartyRole.FROM.equals(p.getRole()));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if no froms found, error, if more than one found, log a warning and use the first one //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(partyList.isEmpty())
|
||||
{
|
||||
throw (new QException("Cannot send SES message because a FROM was not provided."));
|
||||
}
|
||||
else if(partyList.size() > 1)
|
||||
{
|
||||
LOG.warn("More than one FROM value was found, will send using the first one found [" + partyList.get(0).getAddress() + "].");
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// return the from address //
|
||||
/////////////////////////////
|
||||
return (partyList.get(0).getAddress());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
List<Party> getPartyListFromParty(Party party)
|
||||
{
|
||||
//////////////////////////////////////////////
|
||||
// get all parties into one list of parties //
|
||||
//////////////////////////////////////////////
|
||||
List<Party> partyList = new ArrayList<>();
|
||||
if(party != null)
|
||||
{
|
||||
if(party instanceof MultiParty toMultiParty)
|
||||
{
|
||||
partyList.addAll(toMultiParty.getPartyList());
|
||||
}
|
||||
else
|
||||
{
|
||||
partyList.add(party);
|
||||
}
|
||||
}
|
||||
return (partyList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
Destination buildDestination(SendMessageInput input) throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// iterate over the parties putting it the proper party type list //
|
||||
////////////////////////////////////////////////////////////////////
|
||||
List<String> toList = new ArrayList<>();
|
||||
List<String> ccList = new ArrayList<>();
|
||||
List<String> bccList = new ArrayList<>();
|
||||
|
||||
List<Party> partyList = getPartyListFromParty(input.getTo());
|
||||
for(Party party : partyList)
|
||||
{
|
||||
if(EmailPartyRole.CC.equals(party.getRole()))
|
||||
{
|
||||
ccList.add(party.getAddress());
|
||||
}
|
||||
else if(EmailPartyRole.BCC.equals(party.getRole()))
|
||||
{
|
||||
bccList.add(party.getAddress());
|
||||
}
|
||||
else if(party.getRole() == null || PartyRole.Default.DEFAULT.equals(party.getRole()) || EmailPartyRole.TO.equals(party.getRole()))
|
||||
{
|
||||
toList.add(party.getAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (new QException("An unrecognized recipient role of [" + party.getRole() + "] was provided."));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// if no to addresses, this is an error //
|
||||
//////////////////////////////////////////
|
||||
if(toList.isEmpty())
|
||||
{
|
||||
throw (new QException("Cannot send SES message because no TO addresses were provided."));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// build and return aws destination object //
|
||||
/////////////////////////////////////////////
|
||||
return (new Destination()
|
||||
.withToAddresses(toList)
|
||||
.withCcAddresses(ccList)
|
||||
.withBccAddresses(bccList));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Set the amazonSES object.
|
||||
*******************************************************************************/
|
||||
public void setAmazonSES(AmazonSimpleEmailService amazonSES)
|
||||
{
|
||||
this.amazonSES = amazonSES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Internal accessor for the amazonSES object - should always use this, not the field.
|
||||
*******************************************************************************/
|
||||
protected AmazonSimpleEmailService getAmazonSES(SendMessageInput sendMessageInput)
|
||||
{
|
||||
if(amazonSES == null)
|
||||
{
|
||||
SESMessagingProviderMetaData messagingProvider = (SESMessagingProviderMetaData) QContext.getQInstance().getMessagingProvider(sendMessageInput.getMessagingProviderName());
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// get credentials and build an SES client //
|
||||
/////////////////////////////////////////////
|
||||
BasicAWSCredentials credentials = new BasicAWSCredentials(messagingProvider.getAccessKey(), messagingProvider.getSecretKey());
|
||||
amazonSES = AmazonSimpleEmailServiceClientBuilder.standard()
|
||||
.withCredentials(new AWSStaticCredentialsProvider(credentials))
|
||||
.withRegion(messagingProvider.getRegion()).build();
|
||||
}
|
||||
|
||||
return amazonSES;
|
||||
}
|
||||
}
|
@ -31,13 +31,21 @@ import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.actions.messaging.SendMessageAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.StorageAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.Content;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.MultiParty;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.Party;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.SendMessageInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.email.EmailContentRole;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.email.EmailPartyRole;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
|
||||
@ -53,6 +61,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.savedreports.RenderedReport;
|
||||
import com.kingsrook.qqq.backend.core.model.savedreports.RenderedReportStatus;
|
||||
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
@ -82,10 +91,14 @@ public class RenderSavedReportExecuteStep implements BackendStep
|
||||
////////////////////////////////
|
||||
String storageTableName = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_STORAGE_TABLE_NAME);
|
||||
ReportFormat reportFormat = ReportFormat.fromString(runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_REPORT_FORMAT));
|
||||
String sendToEmailAddress = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_EMAIL_ADDRESS);
|
||||
SavedReport savedReport = new SavedReport(runBackendStepInput.getRecords().get(0));
|
||||
String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, savedReport);
|
||||
String storageReference = LocalDate.now() + "/" + LocalTime.now().toString().replaceAll(":", "").replaceFirst("\\..*", "") + "/" + UUID.randomUUID() + "/" + downloadFileBaseName + "." + reportFormat.getExtension();
|
||||
OutputStream outputStream = new StorageAction().createOutputStream(new StorageInput(storageTableName).withReference(storageReference));
|
||||
|
||||
StorageAction storageAction = new StorageAction();
|
||||
StorageInput storageInput = new StorageInput(storageTableName).withReference(storageReference);
|
||||
OutputStream outputStream = storageAction.createOutputStream(storageInput);
|
||||
|
||||
LOG.info("Starting to render a report", logPair("savedReportId", savedReport.getId()), logPair("tableName", savedReport.getTableName()), logPair("storageReference", storageReference));
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Generating Report");
|
||||
@ -120,6 +133,7 @@ public class RenderSavedReportExecuteStep implements BackendStep
|
||||
reportInput.setInputValues(values);
|
||||
|
||||
ReportOutput reportOutput = new GenerateReportAction().execute(reportInput);
|
||||
storageAction.makePublic(storageInput);
|
||||
|
||||
///////////////////////////////////
|
||||
// update record to show success //
|
||||
@ -132,10 +146,28 @@ public class RenderSavedReportExecuteStep implements BackendStep
|
||||
.withValue("rowCount", reportOutput.getTotalRecordCount())
|
||||
));
|
||||
|
||||
runBackendStepOutput.addValue("downloadFileName", downloadFileBaseName + "." + reportFormat.getExtension());
|
||||
String downloadFileName = downloadFileBaseName + "." + reportFormat.getExtension();
|
||||
runBackendStepOutput.addValue("downloadFileName", downloadFileName);
|
||||
runBackendStepOutput.addValue("storageTableName", storageTableName);
|
||||
runBackendStepOutput.addValue("storageReference", storageReference);
|
||||
LOG.info("Completed rendering a report", logPair("savedReportId", savedReport.getId()), logPair("tableName", savedReport.getTableName()), logPair("storageReference", storageReference), logPair("rowCount", reportOutput.getTotalRecordCount()));
|
||||
|
||||
if(sendToEmailAddress != null && CollectionUtils.nullSafeHasContents(QContext.getQInstance().getMessagingProviders()))
|
||||
{
|
||||
String s3Url = "https://bucket-ctlive-reports-dev.s3.us-east-2.amazonaws.com/saved-reports/" + storageReference; // TODO: derp
|
||||
|
||||
new SendMessageAction().execute(new SendMessageInput()
|
||||
.withMessagingProviderName("defaultMessagingProvider") // TODO: derp
|
||||
.withTo(new Party().withAddress(sendToEmailAddress).withRole(EmailPartyRole.TO))
|
||||
.withFrom(new MultiParty()
|
||||
.withParty(new Party().withAddress("reports@coldtrack-dev.com").withRole(EmailPartyRole.FROM)) // TODO: derp
|
||||
.withParty(new Party().withAddress("noreply@coldtrack-dev.com").withRole(EmailPartyRole.REPLY_TO)) // TODO: derp
|
||||
)
|
||||
.withSubject(downloadFileBaseName)
|
||||
.withContent(new Content().withContentRole(EmailContentRole.TEXT).withBody("To download your report, open this URL in your browser: " + s3Url))
|
||||
.withContent(new Content().withContentRole(EmailContentRole.HTML).withBody("Link: <a target=\"_blank\" href=\"" + s3Url + "\">" + downloadFileName + "</a>"))
|
||||
);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -49,6 +49,7 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf
|
||||
|
||||
public static final String FIELD_NAME_STORAGE_TABLE_NAME = "storageTableName";
|
||||
public static final String FIELD_NAME_REPORT_FORMAT = "reportFormat";
|
||||
public static final String FIELD_NAME_EMAIL_ADDRESS = "reportDestinationEmailAddress";
|
||||
|
||||
|
||||
|
||||
@ -74,7 +75,8 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf
|
||||
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.EDIT_FORM))
|
||||
.withFormField(new QFieldMetaData(FIELD_NAME_REPORT_FORMAT, QFieldType.STRING)
|
||||
.withPossibleValueSourceName(ReportFormatPossibleValueEnum.NAME)
|
||||
.withIsRequired(true)))
|
||||
.withIsRequired(true))
|
||||
.withFormField(new QFieldMetaData(FIELD_NAME_EMAIL_ADDRESS, QFieldType.STRING).withLabel("Send To Email Address")))
|
||||
.addStep(new QBackendStepMetaData()
|
||||
.withName("execute")
|
||||
.withInputData(new QFunctionInputMetaData().withRecordListMetaData(new QRecordListMetaData()
|
||||
|
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.model.metadata.messaging.ses;
|
||||
|
||||
|
||||
import cloud.localstack.ServiceName;
|
||||
import cloud.localstack.docker.LocalstackDockerExtension;
|
||||
import cloud.localstack.docker.annotation.LocalstackDockerProperties;
|
||||
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
|
||||
import com.amazonaws.services.simpleemail.model.Destination;
|
||||
import com.amazonaws.services.simpleemail.model.Message;
|
||||
import com.amazonaws.services.simpleemail.model.VerifyEmailAddressRequest;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.Content;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.MultiParty;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.Party;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.SendMessageInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.email.EmailContentRole;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.messaging.email.EmailPartyRole;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for SendSESAction
|
||||
*******************************************************************************/
|
||||
@ExtendWith(LocalstackDockerExtension.class)
|
||||
@LocalstackDockerProperties(useSingleDockerContainer = true, services = { ServiceName.SES }, portEdge = "2960", portElasticSearch = "2961", imageTag = "1.4")
|
||||
class SendSESActionTest extends BaseTest
|
||||
{
|
||||
public static final String TEST_TO_EMAIL_ADDRESS = "tim-to@coldtrack.com";
|
||||
public static final String TEST_FROM_EMAIL_ADDRESS = "tim-from@coldtrack.com";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Before each unit test, get the test bucket into a known state
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
public void beforeEach()
|
||||
{
|
||||
AmazonSimpleEmailService amazonSES = getAmazonSES();
|
||||
amazonSES.verifyEmailAddress(new VerifyEmailAddressRequest().withEmailAddress(TEST_TO_EMAIL_ADDRESS));
|
||||
amazonSES.verifyEmailAddress(new VerifyEmailAddressRequest().withEmailAddress(TEST_FROM_EMAIL_ADDRESS));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Access a localstack-configured SES client.
|
||||
*******************************************************************************/
|
||||
protected AmazonSimpleEmailService getAmazonSES()
|
||||
{
|
||||
return (cloud.localstack.awssdkv1.TestUtils.getClientSES());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testSendSES() throws QException
|
||||
{
|
||||
SendMessageInput sendMessageInput = new SendMessageInput()
|
||||
.withMessagingProviderName(TestUtils.SES_MESSAGING_PROVIDER_NAME)
|
||||
.withTo(new MultiParty()
|
||||
.withParty(new Party().withAddress(TEST_TO_EMAIL_ADDRESS).withLabel("Test TO").withRole(EmailPartyRole.TO))
|
||||
)
|
||||
.withFrom(new Party().withAddress(TEST_FROM_EMAIL_ADDRESS).withLabel("Test FROM"))
|
||||
.withSubject("This is another qqq test message.")
|
||||
.withContent(new Content().withContentRole(EmailContentRole.TEXT).withBody("This is a text body"))
|
||||
.withContent(new Content().withContentRole(EmailContentRole.HTML).withBody("This <u>is</u> an <b>HTML</b> body!"));
|
||||
|
||||
SendSESAction sendSESAction = new SendSESAction();
|
||||
sendSESAction.setAmazonSES(getAmazonSES());
|
||||
sendSESAction.sendMessage(sendMessageInput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetPartyListFromParty() throws QException
|
||||
{
|
||||
SendSESAction sendSESAction = new SendSESAction();
|
||||
assertEquals(0, sendSESAction.getPartyListFromParty(null).size());
|
||||
assertEquals(1, sendSESAction.getPartyListFromParty(new Party()).size());
|
||||
assertEquals(4, sendSESAction.getPartyListFromParty(
|
||||
new MultiParty()
|
||||
.withParty(new Party())
|
||||
.withParty(new Party())
|
||||
.withParty(new Party())
|
||||
.withParty(new Party())
|
||||
).size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetSource() throws QException
|
||||
{
|
||||
/////////////////////////////////////////////////////////////
|
||||
// assert exception if no from given or one without a FROM //
|
||||
/////////////////////////////////////////////////////////////
|
||||
SendSESAction sendSESAction = new SendSESAction();
|
||||
assertThatThrownBy(() -> sendSESAction.getSource(new SendMessageInput())).isInstanceOf(QException.class).hasMessageContaining("not provided");
|
||||
assertThatThrownBy(() -> sendSESAction.getSource(new SendMessageInput().withFrom(new Party().withRole(EmailPartyRole.REPLY_TO)))).isInstanceOf(QException.class).hasMessageContaining("not provided");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// should only be one source, and should be the first one in multi party since multiple not supported //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
SendMessageInput multiPartyInput = new SendMessageInput().withFrom(new MultiParty()
|
||||
.withParty(new Party().withAddress("test1").withRole(EmailPartyRole.REPLY_TO))
|
||||
.withParty(new Party().withAddress("test2").withRole(EmailPartyRole.FROM))
|
||||
.withParty(new Party().withAddress("test3").withRole(EmailPartyRole.REPLY_TO))
|
||||
.withParty(new Party().withAddress("test4").withRole(EmailPartyRole.FROM))
|
||||
);
|
||||
assertEquals("test2", sendSESAction.getSource(multiPartyInput));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetReplyTos() throws QException
|
||||
{
|
||||
SendMessageInput multiPartyInput = new SendMessageInput()
|
||||
.withFrom(new MultiParty()
|
||||
.withParty(new Party().withAddress("test1").withRole(EmailPartyRole.REPLY_TO))
|
||||
.withParty(new Party().withAddress("test2").withRole(EmailPartyRole.FROM))
|
||||
.withParty(new Party().withAddress("test3").withRole(EmailPartyRole.REPLY_TO))
|
||||
.withParty(new Party().withAddress("test4").withRole(EmailPartyRole.FROM))
|
||||
);
|
||||
SendMessageInput singleInput = new SendMessageInput()
|
||||
.withFrom(new Party().withAddress("test1").withRole(EmailPartyRole.FROM));
|
||||
|
||||
SendSESAction sendSESAction = new SendSESAction();
|
||||
assertEquals(2, sendSESAction.getReplyTos(multiPartyInput).size());
|
||||
assertEquals(0, sendSESAction.getReplyTos(singleInput).size());
|
||||
assertEquals(0, sendSESAction.getReplyTos(null).size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBuildDestination() throws QException
|
||||
{
|
||||
/////////////////////////////////////////
|
||||
// assert exception if no tos provided //
|
||||
/////////////////////////////////////////
|
||||
SendSESAction sendSESAction = new SendSESAction();
|
||||
assertThatThrownBy(() -> sendSESAction.buildDestination(new SendMessageInput())).isInstanceOf(QException.class).hasMessageContaining("were provided");
|
||||
assertThatThrownBy(() -> sendSESAction.buildDestination(new SendMessageInput().withTo(new Party().withAddress("test1").withRole(EmailPartyRole.CC)))).isInstanceOf(QException.class).hasMessageContaining("were provided");
|
||||
|
||||
///////////////////////////////////////////
|
||||
// exception if a FROM given in to field //
|
||||
///////////////////////////////////////////
|
||||
assertThatThrownBy(() -> sendSESAction.buildDestination(new SendMessageInput().withTo(new Party().withAddress("test1").withRole(EmailPartyRole.FROM)))).isInstanceOf(QException.class).hasMessageContaining("unrecognized");
|
||||
|
||||
SendMessageInput multiPartyInput = new SendMessageInput()
|
||||
.withTo(new MultiParty()
|
||||
.withParty(new Party().withAddress("test1").withRole(EmailPartyRole.CC))
|
||||
.withParty(new Party().withAddress("test2").withRole(EmailPartyRole.TO))
|
||||
.withParty(new Party().withAddress("test3").withRole(EmailPartyRole.BCC))
|
||||
.withParty(new Party().withAddress("test4").withRole(EmailPartyRole.BCC))
|
||||
.withParty(new Party().withAddress("test5").withRole(EmailPartyRole.TO))
|
||||
.withParty(new Party().withAddress("test6").withRole(EmailPartyRole.TO))
|
||||
.withParty(new Party().withAddress("test7").withRole(EmailPartyRole.TO))
|
||||
);
|
||||
Destination destination = sendSESAction.buildDestination(multiPartyInput);
|
||||
assertEquals(2, destination.getBccAddresses().size());
|
||||
assertEquals(4, destination.getToAddresses().size());
|
||||
assertEquals(1, destination.getCcAddresses().size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBuildMessage() throws QException
|
||||
{
|
||||
/////////////////////////////////////////
|
||||
// assert exception if no tos provided //
|
||||
/////////////////////////////////////////
|
||||
SendSESAction sendSESAction = new SendSESAction();
|
||||
assertThatThrownBy(() -> sendSESAction.buildMessage(new SendMessageInput())).isInstanceOf(QException.class).hasMessageContaining("'Text' nor an 'HTML'");
|
||||
|
||||
///////////////////////////////////////////
|
||||
// exception if a FROM given in to field //
|
||||
///////////////////////////////////////////
|
||||
assertThatThrownBy(() -> sendSESAction.buildDestination(new SendMessageInput().withTo(new Party().withAddress("test1").withRole(EmailPartyRole.FROM)))).isInstanceOf(QException.class).hasMessageContaining("unrecognized");
|
||||
|
||||
String htmlContent = "HTML_CONTENT";
|
||||
String textContent = "TEXT_CONTENT";
|
||||
String subject = "SUBJECT";
|
||||
SendMessageInput input = new SendMessageInput()
|
||||
.withContent(new Content().withContentRole(EmailContentRole.HTML).withBody(htmlContent))
|
||||
.withContent(new Content().withContentRole(EmailContentRole.TEXT).withBody(textContent))
|
||||
.withSubject(subject);
|
||||
Message message = sendSESAction.buildMessage(input);
|
||||
assertEquals(htmlContent, message.getBody().getHtml().getData());
|
||||
assertEquals(textContent, message.getBody().getText().getData());
|
||||
assertEquals(subject, message.getSubject().getData());
|
||||
}
|
||||
|
||||
}
|
@ -76,6 +76,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.messaging.QMessagingProviderMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.messaging.email.EmailMessagingProviderMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.messaging.ses.SESMessagingProviderMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PVSValueFormatAndFields;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||
@ -183,6 +184,7 @@ public class TestUtils
|
||||
public static final String SECURITY_KEY_TYPE_INTERNAL_OR_EXTERNAL = "internalOrExternal";
|
||||
|
||||
public static final String EMAIL_MESSAGING_PROVIDER_NAME = "email";
|
||||
public static final String SES_MESSAGING_PROVIDER_NAME = "ses";
|
||||
|
||||
public static final String SIMPLE_SCHEDULER_NAME = "simpleScheduler";
|
||||
public static final String TEST_SQS_QUEUE = "testSQSQueue";
|
||||
@ -247,6 +249,7 @@ public class TestUtils
|
||||
qInstance.addQueue(defineTestSqsQueue());
|
||||
|
||||
qInstance.addMessagingProvider(defineEmailMessagingProvider());
|
||||
qInstance.addMessagingProvider(defineSESMessagingProvider());
|
||||
|
||||
defineWidgets(qInstance);
|
||||
defineApps(qInstance);
|
||||
@ -258,6 +261,24 @@ public class TestUtils
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QMessagingProviderMetaData defineSESMessagingProvider()
|
||||
{
|
||||
String accessKey = "MOCK"; // interpreter.interpret("${env.SES_ACCESS_KEY}");
|
||||
String secretKey = "MOCK"; // interpreter.interpret("${env.SES_SECRET_KEY}");
|
||||
String region = "MOCK"; // interpreter.interpret("${env.SES_REGION}");
|
||||
|
||||
return (new SESMessagingProviderMetaData()
|
||||
.withAccessKey(accessKey)
|
||||
.withSecretKey(secretKey)
|
||||
.withRegion(region)
|
||||
.withName(SES_MESSAGING_PROVIDER_NAME));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -26,6 +26,7 @@ import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.CannedAccessControlList;
|
||||
import com.amazonaws.services.s3.model.GetObjectRequest;
|
||||
import com.amazonaws.services.s3.model.S3Object;
|
||||
import com.amazonaws.services.s3.model.S3ObjectInputStream;
|
||||
@ -115,4 +116,27 @@ public class S3StorageAction extends AbstractS3Action implements QStorageInterfa
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void makePublic(StorageInput storageInput) throws QException
|
||||
{
|
||||
try
|
||||
{
|
||||
S3BackendMetaData backend = (S3BackendMetaData) storageInput.getBackend();
|
||||
preAction(backend);
|
||||
|
||||
AmazonS3 amazonS3 = getS3Utils().getAmazonS3();
|
||||
String fullPath = getFullPath(storageInput);
|
||||
amazonS3.setObjectAcl(backend.getBucketName(), fullPath, CannedAccessControlList.PublicRead);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw (new QException("Exception making s3 file publicly available", e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user