mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-09 21:58:42 +02:00
6d025d2dc7
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
634 lines
19 KiB
Go
634 lines
19 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/go-errors/errors"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/phishingclub/phishingclub/data"
|
|
"github.com/phishingclub/phishingclub/errs"
|
|
"github.com/phishingclub/phishingclub/model"
|
|
"github.com/phishingclub/phishingclub/repository"
|
|
"github.com/phishingclub/phishingclub/validate"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// RecipientGroup is a recipient group service
|
|
type RecipientGroup struct {
|
|
Common
|
|
CampaignRepository *repository.Campaign
|
|
CampaignRecipientRepository *repository.CampaignRecipient
|
|
RecipientGroupRepository *repository.RecipientGroup
|
|
RecipientRepository *repository.Recipient
|
|
RecipientService *Recipient
|
|
DB *gorm.DB
|
|
}
|
|
|
|
// Create inserts a new recipient group
|
|
func (r *RecipientGroup) Create(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
group *model.RecipientGroup,
|
|
) (*uuid.UUID, error) {
|
|
ae := NewAuditEvent("RecipientGroup.Create", session)
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return nil, errs.ErrAuthorizationFailed
|
|
}
|
|
// if dynamic, validate that filter fields are present, allowed, and non-empty
|
|
isDynamic := group.IsDynamic.IsSpecified() && !group.IsDynamic.IsNull() && group.IsDynamic.MustGet()
|
|
if isDynamic {
|
|
if err := group.ValidateDynamic(); err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
}
|
|
// check uniqueness
|
|
var companyID *uuid.UUID
|
|
if cid, err := group.CompanyID.Get(); err == nil {
|
|
companyID = &cid
|
|
}
|
|
name := group.Name.MustGet()
|
|
isOK, err := repository.CheckNameIsUnique(
|
|
ctx,
|
|
r.RecipientRepository.DB,
|
|
"recipient_groups",
|
|
name.String(),
|
|
companyID,
|
|
nil,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to check recipient group uniqueness", "error", err)
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
if !isOK {
|
|
r.Logger.Debugw("recipient group is already taken", "name", name.String())
|
|
return nil, validate.WrapErrorWithField(errors.New("is not unique"), "name")
|
|
}
|
|
// insert recipient group
|
|
recipientGroupID, err := r.RecipientGroupRepository.Insert(
|
|
ctx,
|
|
group,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Debugw("failed to create recipient group - failed to insert recipient group",
|
|
"error", err,
|
|
)
|
|
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
ae.Details["id"] = recipientGroupID.String()
|
|
r.AuditLogAuthorized(ae)
|
|
|
|
return recipientGroupID, nil
|
|
}
|
|
|
|
// Import imports recipients into a recipient group
|
|
// if the recipient does not exists, it will be created and added to the group
|
|
// if the recipient exits, it will be updated and added to the group
|
|
func (r *RecipientGroup) Import(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
recipients []*model.Recipient,
|
|
ignoreOverwriteEmptyFields bool,
|
|
recipientGroupID *uuid.UUID,
|
|
companyID *uuid.UUID,
|
|
) (*RecipientImportResult, error) {
|
|
ae := NewAuditEvent("RecipientGroup.Import", session)
|
|
ae.Details["recipientGroupId"] = recipientGroupID.String()
|
|
if companyID != nil {
|
|
ae.Details["companyId"] = companyID.String()
|
|
}
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return nil, err
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return nil, errs.ErrAuthorizationFailed
|
|
}
|
|
if len(recipients) == 0 {
|
|
return nil, validate.WrapErrorWithField(errors.New("no recipients"), "add recipients")
|
|
}
|
|
// check that the recipient group exists
|
|
group, err := r.RecipientGroupRepository.GetByID(
|
|
ctx,
|
|
recipientGroupID,
|
|
&repository.RecipientGroupOption{},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Debugw("failed to import recipients - failed to get recipient group", "error", err)
|
|
return nil, err
|
|
}
|
|
// dynamic groups do not support explicit membership via import
|
|
if group.IsDynamic.IsSpecified() && !group.IsDynamic.IsNull() && group.IsDynamic.MustGet() {
|
|
return nil, validate.WrapErrorWithField(errors.New("cannot import recipients into a dynamic group"), "group")
|
|
}
|
|
result, err := r.RecipientService.Import(
|
|
ctx,
|
|
session,
|
|
recipients,
|
|
ignoreOverwriteEmptyFields,
|
|
companyID,
|
|
)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
// add recpients to group
|
|
err = r.AddRecipients(
|
|
ctx,
|
|
session,
|
|
recipientGroupID,
|
|
result.SuccessIDs,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Debugw("failed to import recipients - failed to add recipients to group",
|
|
"error", err,
|
|
)
|
|
return result, err
|
|
}
|
|
r.AuditLogAuthorized(ae)
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// GetByID returns a recipient group by ID
|
|
func (r *RecipientGroup) GetByID(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
id *uuid.UUID,
|
|
options *repository.RecipientGroupOption,
|
|
) (*model.RecipientGroup, error) {
|
|
ae := NewAuditEvent("RecipientGroup.GetByID", session)
|
|
ae.Details["id"] = id.String()
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return nil, errs.ErrAuthorizationFailed
|
|
}
|
|
// get recipient group
|
|
recipientGroup, err := r.RecipientGroupRepository.GetByID(
|
|
ctx,
|
|
id,
|
|
options,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to get recipient group by id - failed to get recipient group",
|
|
"error", err,
|
|
)
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
// no audit on read
|
|
|
|
return recipientGroup, nil
|
|
}
|
|
|
|
// GetByCompanyID returns recipient groups by company ID
|
|
func (r *RecipientGroup) GetByCompanyID(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
id *uuid.UUID,
|
|
options *repository.RecipientGroupOption,
|
|
) ([]*model.RecipientGroup, error) {
|
|
ae := NewAuditEvent("RecipientGroup.GetByCompanyID", session)
|
|
ae.Details["id"] = id.String()
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return nil, errs.ErrAuthorizationFailed
|
|
}
|
|
// get recipient group
|
|
recipientGroups, err := r.RecipientGroupRepository.GetAllByCompanyID(
|
|
ctx,
|
|
id,
|
|
options,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to get recipient groups by id - failed to get recipient group",
|
|
"error", err,
|
|
)
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
// no audit on read
|
|
|
|
return recipientGroups, nil
|
|
}
|
|
|
|
// GetAll returns all recipient groups using pagination
|
|
func (r *RecipientGroup) GetAll(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
companyID *uuid.UUID, // can be null
|
|
options *repository.RecipientGroupOption,
|
|
) (*model.Result[model.RecipientGroup], error) {
|
|
result := model.NewEmptyResult[model.RecipientGroup]()
|
|
ae := NewAuditEvent("RecipientGroup.GetAll", session)
|
|
if companyID != nil {
|
|
ae.Details["companyId"] = companyID.String()
|
|
}
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return result, errs.Wrap(err)
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return result, errs.ErrAuthorizationFailed
|
|
}
|
|
|
|
// get recipient groups
|
|
result, err = r.RecipientGroupRepository.GetAll(
|
|
ctx,
|
|
companyID,
|
|
options,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to get all recipient groups - failed to get all recipient groups",
|
|
"error", err,
|
|
)
|
|
return result, errs.Wrap(err)
|
|
}
|
|
// no audit log on read
|
|
return result, nil
|
|
}
|
|
|
|
// GetRecipientsByID returns all recipients of a recipient group
|
|
func (r *RecipientGroup) GetRecipientsByGroupID(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
id *uuid.UUID,
|
|
options *repository.RecipientOption,
|
|
) (*model.Result[model.Recipient], error) {
|
|
result := model.NewEmptyResult[model.Recipient]()
|
|
ae := NewAuditEvent("RecipientGroup.GetRecipientsByGroupID", session)
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return result, errs.Wrap(err)
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return result, errs.ErrAuthorizationFailed
|
|
}
|
|
// get recipients
|
|
result, err = r.RecipientGroupRepository.GetRecipientsByGroupID(
|
|
ctx,
|
|
id,
|
|
options,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to get recipients by id - failed to get recipients", "error", err)
|
|
return result, errs.Wrap(err)
|
|
}
|
|
// no audit on read
|
|
return result, nil
|
|
}
|
|
|
|
// UpdateByID updates a recipient group by ID
|
|
func (r *RecipientGroup) UpdateByID(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
id *uuid.UUID,
|
|
incoming *model.RecipientGroup,
|
|
) error {
|
|
ae := NewAuditEvent("RecipientGroup.UpdateByID", session)
|
|
ae.Details["id"] = id.String()
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return err
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return errs.ErrAuthorizationFailed
|
|
}
|
|
// get current
|
|
current, err := r.RecipientGroupRepository.GetByID(
|
|
ctx,
|
|
id,
|
|
&repository.RecipientGroupOption{},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to get recipient group", "error", err)
|
|
return err
|
|
}
|
|
if incoming.Name.IsSpecified() && !incoming.Name.IsNull() {
|
|
var companyID *uuid.UUID
|
|
if cid, err := current.CompanyID.Get(); err == nil {
|
|
companyID = &cid
|
|
}
|
|
name := incoming.Name.MustGet()
|
|
isOK, err := repository.CheckNameIsUnique(
|
|
ctx,
|
|
r.RecipientRepository.DB,
|
|
"recipient_groups",
|
|
name.String(),
|
|
companyID,
|
|
id,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to check recipient group uniqueness", "error", err)
|
|
return err
|
|
}
|
|
if !isOK {
|
|
r.Logger.Debugw("recipient group is already taken", "name", name.String())
|
|
return validate.WrapErrorWithField(errors.New("is not unique"), "name")
|
|
}
|
|
current.Name.Set(name)
|
|
}
|
|
// disallow toggling isDynamic after creation
|
|
if incoming.IsDynamic.IsSpecified() && !incoming.IsDynamic.IsNull() {
|
|
currentIsDynamic := current.IsDynamic.IsSpecified() && !current.IsDynamic.IsNull() && current.IsDynamic.MustGet()
|
|
if incoming.IsDynamic.MustGet() != currentIsDynamic {
|
|
return validate.WrapErrorWithField(errors.New("cannot change after creation"), "isDynamic")
|
|
}
|
|
}
|
|
|
|
isDynamic := current.IsDynamic.IsSpecified() && !current.IsDynamic.IsNull() && current.IsDynamic.MustGet()
|
|
if isDynamic {
|
|
// propagate filter field/value updates; ValidateDynamic carries the allowlist check
|
|
if incoming.FilterField.IsSpecified() && !incoming.FilterField.IsNull() {
|
|
current.FilterField.Set(incoming.FilterField.MustGet())
|
|
}
|
|
if incoming.FilterValue.IsSpecified() && !incoming.FilterValue.IsNull() {
|
|
current.FilterValue.Set(incoming.FilterValue.MustGet())
|
|
}
|
|
// re-validate the merged state so allowlist and length rules are enforced
|
|
if err := current.ValidateDynamic(); err != nil {
|
|
return errs.Wrap(err)
|
|
}
|
|
} else {
|
|
// reject filter field/value changes on a static group
|
|
if (incoming.FilterField.IsSpecified() && !incoming.FilterField.IsNull()) ||
|
|
(incoming.FilterValue.IsSpecified() && !incoming.FilterValue.IsNull()) {
|
|
return validate.WrapErrorWithField(errors.New("cannot set filter fields on a static group"), "filterField")
|
|
}
|
|
}
|
|
// update recipient group
|
|
err = r.RecipientGroupRepository.UpdateByID(
|
|
ctx,
|
|
id,
|
|
current,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to update recipient group by id - failed to update recipient group",
|
|
"error", err,
|
|
)
|
|
return err
|
|
}
|
|
r.AuditLogAuthorized(ae)
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddRecipients adds recipients to a recipient group.
|
|
// returns an error if the group is dynamic, as membership is derived from the filter query.
|
|
func (r *RecipientGroup) AddRecipients(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
groupID *uuid.UUID,
|
|
recipients []*uuid.UUID,
|
|
) error {
|
|
ae := NewAuditEvent("RecipientGroup.AddRecipients", session)
|
|
ae.Details["id"] = groupID.String()
|
|
ae.Details["recipientIds"] = repository.UUIDsToStrings(recipients)
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return err
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return errs.ErrAuthorizationFailed
|
|
}
|
|
// ensure that the recipient group exists
|
|
group, err := r.RecipientGroupRepository.GetByID(
|
|
ctx,
|
|
groupID,
|
|
&repository.RecipientGroupOption{},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to add recipients - failed to get recipient group", "error", err)
|
|
return err
|
|
}
|
|
// dynamic groups do not support explicit membership
|
|
if group.IsDynamic.IsSpecified() && !group.IsDynamic.IsNull() && group.IsDynamic.MustGet() {
|
|
return validate.WrapErrorWithField(errors.New("cannot add recipients to a dynamic group"), "group")
|
|
}
|
|
// check if the recipients can be added to group
|
|
for _, recipientID := range recipients {
|
|
recipient, err := r.RecipientRepository.GetByID(
|
|
ctx,
|
|
recipientID,
|
|
&repository.RecipientOption{},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to add recipients - failed to get recipient by id",
|
|
"error", err,
|
|
)
|
|
return err
|
|
}
|
|
// if the group has a company ID then the recipients company ID must match
|
|
// unless the recipient has no company id as it is global
|
|
if v, err := group.CompanyID.Get(); err == nil {
|
|
// if the recipient company is set and does not match the groups
|
|
if recipient.CompanyID.IsSpecified() && !recipient.CompanyID.IsNull() && v.String() != recipient.CompanyID.MustGet().String() {
|
|
|
|
r.Logger.Errorw("failed to add recipients - recipient company id does not match group id",
|
|
"error", err,
|
|
)
|
|
return validate.WrapErrorWithField(errors.New("company id does not match group id"), "recipient")
|
|
}
|
|
} else {
|
|
// if the group does not have a company ID then the recipient must not have a company ID
|
|
if recipient.CompanyID.IsSpecified() && !recipient.CompanyID.IsNull() {
|
|
r.Logger.Errorw("failed to add recipients - recipient company id is not nil", "error", err)
|
|
return validate.WrapErrorWithField(errors.New("cant add recipient belonging to a company to a global group"), "recipient")
|
|
}
|
|
}
|
|
}
|
|
// add recipients to group
|
|
err = r.RecipientGroupRepository.AddRecipients(
|
|
ctx,
|
|
groupID,
|
|
recipients,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to add recipients - failed to add recipients to group", "error", err)
|
|
return err
|
|
}
|
|
r.AuditLogAuthorized(ae)
|
|
|
|
return nil
|
|
}
|
|
|
|
// RemoveRecipients removes recipients from a recipient group.
|
|
// returns an error if the group is dynamic, as membership is derived from the filter query.
|
|
func (r *RecipientGroup) RemoveRecipients(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
groupID *uuid.UUID,
|
|
recipientIDs []*uuid.UUID,
|
|
) error {
|
|
ae := NewAuditEvent("RecipientGroup.RemoveRecipients", session)
|
|
ae.Details["groupId"] = groupID.String()
|
|
ae.Details["recipientIds"] = repository.UUIDsToStrings(recipientIDs)
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return err
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return errs.ErrAuthorizationFailed
|
|
}
|
|
// dynamic groups do not support explicit membership removal
|
|
existingGroup, err := r.RecipientGroupRepository.GetByID(
|
|
ctx,
|
|
groupID,
|
|
&repository.RecipientGroupOption{},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to remove recipients - failed to get recipient group", "error", err)
|
|
return err
|
|
}
|
|
if existingGroup.IsDynamic.IsSpecified() && !existingGroup.IsDynamic.IsNull() && existingGroup.IsDynamic.MustGet() {
|
|
return validate.WrapErrorWithField(errors.New("cannot remove recipients from a dynamic group"), "group")
|
|
}
|
|
// cancel any pending sends for these recipients in active campaigns; the
|
|
// recipients are kept and their campaign history is left intact
|
|
for _, recpID := range recipientIDs {
|
|
err = r.CampaignRecipientRepository.CancelInActiveCampaigns(ctx, recpID)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to cancel campaign recipient", "error", err)
|
|
return err
|
|
}
|
|
}
|
|
// remove recipient from group
|
|
err = r.RecipientGroupRepository.RemoveRecipients(
|
|
ctx,
|
|
groupID,
|
|
recipientIDs,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to remove recipient - failed to remove recipient from group",
|
|
"error", err,
|
|
)
|
|
return err
|
|
}
|
|
r.AuditLogAuthorized(ae)
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteByID deletes a recipient group by ID
|
|
func (r *RecipientGroup) DeleteByID(
|
|
ctx context.Context,
|
|
session *model.Session,
|
|
id *uuid.UUID,
|
|
) error {
|
|
ae := NewAuditEvent("RecipientGroup.DeleteByID", session)
|
|
ae.Details["id"] = id.String()
|
|
// check permissions
|
|
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
|
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
|
r.LogAuthError(err)
|
|
return err
|
|
}
|
|
if !isAuthorized {
|
|
r.AuditLogNotAuthorized(ae)
|
|
return errs.ErrAuthorizationFailed
|
|
}
|
|
// get all recipients in group; for dynamic groups the junction table is empty so we
|
|
// must resolve members via the filter query before anonymizing campaign data
|
|
group, err := r.RecipientGroupRepository.GetByID(
|
|
ctx,
|
|
id,
|
|
&repository.RecipientGroupOption{
|
|
WithRecipients: true,
|
|
},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to delete recipient group - failed to get recipient group", "error", err)
|
|
return err
|
|
}
|
|
|
|
recipients := group.Recipients
|
|
isDynamic := group.IsDynamic.IsSpecified() && !group.IsDynamic.IsNull() && group.IsDynamic.MustGet()
|
|
if isDynamic {
|
|
// dynamic groups carry no junction-table rows; resolve members via filter query
|
|
dynamicResult, err := r.RecipientGroupRepository.GetRecipientsByGroupID(
|
|
ctx,
|
|
id,
|
|
&repository.RecipientOption{},
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to delete recipient group - failed to get dynamic group recipients", "error", err)
|
|
return err
|
|
}
|
|
recipients = dynamicResult.Rows
|
|
}
|
|
|
|
if len(recipients) > 0 {
|
|
// cancel any pending sends for these recipients in active campaigns; the
|
|
// recipients are kept and their campaign history is left intact
|
|
for _, recipient := range recipients {
|
|
recpID := recipient.ID.MustGet()
|
|
err = r.CampaignRecipientRepository.CancelInActiveCampaigns(ctx, &recpID)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to cancel campaign recipient", "error", err)
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
// remove group from campaign groups
|
|
err = r.CampaignRepository.RemoveCampaignRecipientGroupByGroupID(
|
|
ctx,
|
|
id,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw(
|
|
"failed to delete group - failed remove group from campaign data",
|
|
"error", err,
|
|
)
|
|
return err
|
|
}
|
|
// remove group and recipients from group
|
|
err = r.RecipientGroupRepository.DeleteByID(
|
|
ctx,
|
|
id,
|
|
)
|
|
if err != nil {
|
|
r.Logger.Errorw("failed to delete recipient group by id - failed to delete recipient group",
|
|
"error", err,
|
|
)
|
|
return err
|
|
}
|
|
r.AuditLogAuthorized(ae)
|
|
|
|
return nil
|
|
}
|