mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-06 12:27:58 +02:00
fix missing cascading of deleting an email used by templates or campaigns
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -184,14 +184,15 @@ func NewServices(
|
||||
}
|
||||
ipAllowListService := service.NewIPAllowListService(logger, repositories.Proxy)
|
||||
email := &service.Email{
|
||||
Common: common,
|
||||
AttachmentPath: attachmentPath,
|
||||
AttachmentService: attachment,
|
||||
DomainService: domain,
|
||||
EmailRepository: repositories.Email,
|
||||
SMTPService: smtpConfiguration,
|
||||
RecipientService: recipient,
|
||||
TemplateService: templateService,
|
||||
Common: common,
|
||||
AttachmentPath: attachmentPath,
|
||||
AttachmentService: attachment,
|
||||
DomainService: domain,
|
||||
EmailRepository: repositories.Email,
|
||||
SMTPService: smtpConfiguration,
|
||||
RecipientService: recipient,
|
||||
TemplateService: templateService,
|
||||
CampaignTemplateService: campaignTemplate,
|
||||
}
|
||||
campaign := &service.Campaign{
|
||||
Common: common,
|
||||
|
||||
@@ -657,6 +657,70 @@ func (r *CampaignTemplate) RemoveSmtpIDFromAll(
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetByEmailID gets all campaign templates by email ID
|
||||
func (r *CampaignTemplate) GetByEmailID(
|
||||
ctx context.Context,
|
||||
emailID *uuid.UUID,
|
||||
options *CampaignTemplateOption,
|
||||
) ([]*model.CampaignTemplate, error) {
|
||||
db := r.DB
|
||||
if options.Columns != nil && len(options.Columns) > 0 {
|
||||
db = db.Select(strings.Join(options.Columns, ","))
|
||||
}
|
||||
db = r.load(options, db)
|
||||
db, err := useQuery(db, database.CAMPAIGN_TEMPLATE_TABLE, options.QueryArgs, allowdCampaignTemplatesColumns...)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
db = db.Where(
|
||||
fmt.Sprintf(
|
||||
"%s = ?",
|
||||
TableColumn(database.CAMPAIGN_TEMPLATE_TABLE, "email_id"),
|
||||
),
|
||||
emailID.String(),
|
||||
)
|
||||
var tmpl []database.CampaignTemplate
|
||||
res := db.Find(&tmpl)
|
||||
if res.Error != nil {
|
||||
return nil, res.Error
|
||||
}
|
||||
templates := []*model.CampaignTemplate{}
|
||||
for _, t := range tmpl {
|
||||
tmpl, err := ToCampaignTemplate(&t)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
templates = append(templates, tmpl)
|
||||
}
|
||||
return templates, nil
|
||||
}
|
||||
|
||||
// RemoveEmailIDFromAll removes the email ID from all campaign templates that reference it
|
||||
// and marks them as not usable
|
||||
func (r *CampaignTemplate) RemoveEmailIDFromAll(
|
||||
ctx context.Context,
|
||||
emailID *uuid.UUID,
|
||||
) error {
|
||||
row := map[string]any{}
|
||||
AddUpdatedAt(row)
|
||||
row["email_id"] = nil
|
||||
row["is_usable"] = false
|
||||
res := r.DB.
|
||||
Model(&database.CampaignTemplate{}).
|
||||
Where(
|
||||
fmt.Sprintf(
|
||||
"%s = ?",
|
||||
TableColumn(database.CAMPAIGN_TEMPLATE_TABLE, "email_id"),
|
||||
),
|
||||
emailID.String(),
|
||||
).
|
||||
Updates(row)
|
||||
if res.Error != nil {
|
||||
return res.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemovePageIDFromAll removes the page ID from any matching columns
|
||||
// landing_page_id, before_landing_page_id and after_landing_page_id
|
||||
func (r *CampaignTemplate) RemovePageIDFromAll(
|
||||
|
||||
@@ -412,6 +412,73 @@ func (c *CampaignTemplate) RemoveSmtpBySmtpID(
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveEmailByEmailID removes the email ID from all campaign templates that reference it,
|
||||
// marks them as not usable, and closes any active campaigns that use those templates.
|
||||
func (c *CampaignTemplate) RemoveEmailByEmailID(
|
||||
ctx context.Context,
|
||||
session *model.Session,
|
||||
emailID *uuid.UUID,
|
||||
) error {
|
||||
ae := NewAuditEvent("CampaignTemplate.RemoveEmailByEmailID", session)
|
||||
ae.Details["emailId"] = emailID.String()
|
||||
// check permissions
|
||||
isAuthorized, err := IsAuthorized(session, data.PERMISSION_ALLOW_GLOBAL)
|
||||
if err != nil && !errors.Is(err, errs.ErrAuthorizationFailed) {
|
||||
c.LogAuthError(err)
|
||||
return err
|
||||
}
|
||||
if !isAuthorized {
|
||||
c.AuditLogNotAuthorized(ae)
|
||||
return errs.ErrAuthorizationFailed
|
||||
}
|
||||
// find all campaign templates that reference this email
|
||||
templatesAffected, err := c.CampaignTemplateRepository.GetByEmailID(
|
||||
ctx,
|
||||
emailID,
|
||||
&repository.CampaignTemplateOption{},
|
||||
)
|
||||
if err != nil {
|
||||
c.Logger.Errorw("failed to get affected campaign templates", "error", err)
|
||||
return err
|
||||
}
|
||||
templateIDs := []*uuid.UUID{}
|
||||
for _, t := range templatesAffected {
|
||||
id := t.ID.MustGet()
|
||||
templateIDs = append(templateIDs, &id)
|
||||
}
|
||||
// close any active campaigns that use the affected templates
|
||||
campaignsAffected, err := c.CampaignRepository.GetByTemplateIDs(ctx, templateIDs)
|
||||
if err != nil {
|
||||
c.Logger.Errorw("failed to get affected campaigns", "error", err)
|
||||
return err
|
||||
}
|
||||
for _, campaign := range campaignsAffected {
|
||||
if !campaign.IsActive() {
|
||||
continue
|
||||
}
|
||||
err := campaign.Close()
|
||||
if err != nil {
|
||||
c.Logger.Errorw("failed to close campaign", "error", err)
|
||||
}
|
||||
campaignID := campaign.ID.MustGet()
|
||||
err = c.CampaignRepository.UpdateByID(
|
||||
ctx,
|
||||
&campaignID,
|
||||
campaign,
|
||||
)
|
||||
if err != nil {
|
||||
c.Logger.Errorw("failed to update closed campaign", "error", err)
|
||||
}
|
||||
}
|
||||
// remove the email id from all affected templates
|
||||
err = c.CampaignTemplateRepository.RemoveEmailIDFromAll(ctx, emailID)
|
||||
if err != nil {
|
||||
c.Logger.Errorw("failed to remove email ID from all campaign templates", "error", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemovePageByPageID removes the page ID from a template
|
||||
// this makes the template unusable until a domain has been added.
|
||||
func (c *CampaignTemplate) RemovePagesByPageID(
|
||||
|
||||
@@ -28,13 +28,14 @@ import (
|
||||
// Email is a Email service
|
||||
type Email struct {
|
||||
Common
|
||||
EmailRepository *repository.Email
|
||||
SMTPService *SMTPConfiguration
|
||||
DomainService *Domain
|
||||
RecipientService *Recipient
|
||||
TemplateService *Template
|
||||
AttachmentService *Attachment
|
||||
AttachmentPath string
|
||||
EmailRepository *repository.Email
|
||||
SMTPService *SMTPConfiguration
|
||||
DomainService *Domain
|
||||
RecipientService *Recipient
|
||||
TemplateService *Template
|
||||
AttachmentService *Attachment
|
||||
CampaignTemplateService *CampaignTemplate
|
||||
AttachmentPath string
|
||||
}
|
||||
|
||||
// AttachmentWithInline represents an attachment with inline flag
|
||||
@@ -947,6 +948,17 @@ func (m *Email) DeleteByID(
|
||||
m.AuditLogNotAuthorized(ae)
|
||||
return errs.ErrAuthorizationFailed
|
||||
}
|
||||
// remove the email from any campaign templates that reference it and close
|
||||
// any active campaigns that use those templates
|
||||
err = m.CampaignTemplateService.RemoveEmailByEmailID(
|
||||
ctx,
|
||||
session,
|
||||
id,
|
||||
)
|
||||
if err != nil {
|
||||
m.Logger.Errorw("failed to remove email relation from campaign templates", "error", err)
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
// delete email by id
|
||||
err = m.EmailRepository.DeleteByID(
|
||||
ctx,
|
||||
|
||||
Reference in New Issue
Block a user