Files
phishingclub/backend/seed/recipient_dev.go
2025-08-21 16:14:09 +02:00

390 lines
10 KiB
Go

//go:build dev
package seed
import (
"context"
"strings"
"github.com/go-errors/errors"
"github.com/brianvoe/gofakeit/v7"
"github.com/google/uuid"
"github.com/oapi-codegen/nullable"
"github.com/phishingclub/phishingclub/errs"
"github.com/phishingclub/phishingclub/model"
"github.com/phishingclub/phishingclub/repository"
"github.com/phishingclub/phishingclub/vo"
"gorm.io/gorm"
)
type DevelopmentRecipient struct {
FirstName string
LastName string
Email string
Department string
Position string
ExtraIdentifier string
Phone string
City string
Country string
Misc string
CompanyID string
}
// tcmpRecpMap holds the company name and the recipient emails
// so it can later be added to different groups
// map[companyID][]recpUUID
var tmpRecpMap = map[string][]*uuid.UUID{}
func SeedDevelopmentRecipients(
recipientRepository *repository.Recipient,
companyRepository *repository.Company,
faker *gofakeit.Faker,
) error {
// add known recipients
recipients := []DevelopmentRecipient{
{
Email: TEST_RECIPIENT_EMAIL_1,
FirstName: "Alice",
LastName: "",
Department: "Economy",
},
{
Email: TEST_RECIPIENT_EMAIL_2,
FirstName: "Bob",
LastName: "",
Department: "Economy",
},
{
Email: TEST_RECIPIENT_EMAIL_3,
FirstName: "Mallory",
LastName: "",
Department: "Marketing",
},
{
Email: TEST_RECIPIENT_EMAIL_4,
FirstName: "Vickey",
LastName: "",
Department: "Marketing",
},
}
// add random recipients
country := faker.Country()
domain := faker.DomainName()
jobLevels := []string{}
for i := 0; i < 3; i++ {
jobLevels = append(jobLevels, faker.JobLevel())
}
for i := 0; i < 10; i++ {
firstName := faker.FirstName()
lastName := faker.LastName()
jobLevel := jobLevels[faker.Number(0, len(jobLevels)-1)]
emailPrefix := strings.ToLower(strings.Join(strings.Split(firstName, " "), "."))
recipients = append(recipients, DevelopmentRecipient{
Email: emailPrefix + "@" + domain,
FirstName: firstName,
LastName: lastName,
Department: jobLevel,
Position: faker.JobTitle(),
City: faker.City(),
Phone: faker.Phone(),
Country: country,
Misc: faker.Sentence(10),
})
}
err := createDevelopmentRecipients(recipients, recipientRepository)
if err != nil {
return errors.Errorf("failed to seed development recipients: %w", err)
}
// random recipients attached to companies
err = forEachDevelopmentCompany(companyRepository, func(company *model.Company) error {
recipients := []DevelopmentRecipient{}
country = faker.Country()
domain := faker.DomainName()
jobLevels := []string{}
for i := 0; i < 3; i++ {
jobLevels = append(jobLevels, faker.JobLevel())
}
for i := 0; i < 10; i++ {
jobLevel := jobLevels[faker.Number(0, len(jobLevels)-1)]
//emailPrefix := faker.Username()
firstName := faker.FirstName()
lastName := faker.LastName()
emailPrefix := strings.ToLower(strings.Join(strings.Split(firstName, " "), "."))
country := faker.Country()
recipients = append(recipients, DevelopmentRecipient{
Email: emailPrefix + "@" + domain,
FirstName: firstName,
LastName: lastName,
Department: jobLevel,
Position: faker.JobTitle(),
City: faker.City(),
Country: country,
CompanyID: company.ID.MustGet().String(),
})
}
err := createDevelopmentRecipients(recipients, recipientRepository)
if err != nil {
return errors.Errorf("failed to seed development recipients: %w", err)
}
return nil
})
if err != nil {
return errors.Errorf("failed to seed development recipients: %w", err)
}
// TODO remove the tmp data, not sure why but last i removed it, it
// broke the seeding of the company data
//tmpRecpMap = map[string][]*uuid.UUID{}
return nil
}
// SeedDevelopmentRecipientGroups seeds recipient groups
func SeedDevelopmentRecipientGroups(
faker *gofakeit.Faker,
companyRepository *repository.Company,
recipientRepository *repository.Recipient,
recipientGroupRepository *repository.RecipientGroup,
) error {
// recipients holds the recipients we want to add to the recipient group
recipients := []*struct {
Email string
Model *model.Recipient
Group string
}{
{
Email: TEST_RECIPIENT_EMAIL_1,
Model: nil,
Group: TEST_RECIPIENT_GROUP_NAME_1,
},
{
Email: TEST_RECIPIENT_EMAIL_2,
Model: nil,
Group: TEST_RECIPIENT_GROUP_NAME_1,
},
{
Email: TEST_RECIPIENT_EMAIL_3,
Model: nil,
Group: TEST_RECIPIENT_GROUP_NAME_2,
},
{
Email: TEST_RECIPIENT_EMAIL_4,
Model: nil,
Group: TEST_RECIPIENT_GROUP_NAME_2,
},
}
for _, recipient := range recipients {
email, err := vo.NewEmail(recipient.Email)
if err != nil {
return errors.Errorf("%w: %s", errs.ErrDBSeedFailure, err)
}
recp, err := recipientRepository.GetByEmailAndCompanyID(
context.Background(),
email,
nil,
)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return errors.Errorf("%w: %s", errs.ErrDBSeedFailure, err)
}
if recp == nil {
return errors.Errorf("%w: %s", errs.ErrDBSeedFailure, "recipient not found")
}
recipient.Model = recp
}
recipientGroups := []struct {
Name string
}{
{
Name: TEST_RECIPIENT_GROUP_NAME_1,
},
{
Name: TEST_RECIPIENT_GROUP_NAME_2,
},
}
for _, recipientGroup := range recipientGroups {
rgID := nullable.NewNullableWithValue(uuid.New())
name := nullable.NewNullableWithValue(*vo.NewString127Must(recipientGroup.Name))
rg := model.RecipientGroup{
ID: rgID,
Name: name,
}
r, err := recipientGroupRepository.GetByNameAndCompanyID(
context.Background(),
name.MustGet().String(),
nil,
&repository.RecipientGroupOption{},
)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return errors.Errorf("%w: %s", errs.ErrDBSeedFailure, err)
}
if r != nil {
continue
}
id, err := recipientGroupRepository.Insert(
context.Background(),
&rg,
)
if err != nil {
return errors.Errorf("%w: %s", errs.ErrDBSeedFailure, err)
}
recpUUIDs := []*uuid.UUID{}
for _, recipient := range recipients {
if recipient.Group == recipientGroup.Name {
id := recipient.Model.ID.MustGet()
recpUUIDs = append(recpUUIDs, &id)
}
}
err = recipientGroupRepository.AddRecipients(
context.Background(),
id,
recpUUIDs,
)
if err != nil {
return errors.Errorf("%w: %s", errs.ErrDBSeedFailure, err)
}
}
// add random company recipients to random recipient groups
err := forEachDevelopmentCompany(companyRepository, func(company *model.Company) error {
companyID := company.ID.MustGet()
groupNameVO := vo.NewString127Must(faker.BuzzWord())
groupName := nullable.NewNullableWithValue(
*groupNameVO,
)
recpUUIDs := tmpRecpMap[companyID.String()]
// create the group
rg := model.RecipientGroup{
Name: groupName,
CompanyID: company.ID,
}
r, err := recipientGroupRepository.GetByNameAndCompanyID(
context.Background(),
groupNameVO.String(),
&companyID,
&repository.RecipientGroupOption{},
)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return errors.Errorf("query failed: %s", err)
}
if r != nil {
return nil
}
id, err := recipientGroupRepository.Insert(
context.Background(),
&rg,
)
if err != nil {
return errors.Errorf("insert failed: %s", err)
}
err = recipientGroupRepository.AddRecipients(
context.Background(),
id,
recpUUIDs,
)
if err != nil {
return errors.Errorf(
"failed to add recipients to group with (groupID: %s and recipients: %s): %w",
id,
recpUUIDs,
err,
)
}
return nil
})
if err != nil {
return errors.Errorf("failed to create company data: %s", err)
}
return nil
}
func createDevelopmentRecipients(
devRecps []DevelopmentRecipient,
recipientRepository *repository.Recipient,
) error {
for _, recipient := range devRecps {
firstName := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.FirstName),
)
lastName := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.LastName),
)
email := nullable.NewNullNullable[vo.Email]()
if recipient.Email != "" {
email.Set(*vo.NewEmailMust(recipient.Email))
}
department := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.Department),
)
position := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.Position),
)
phone := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.Phone),
)
extraIdentifier := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.ExtraIdentifier),
)
city := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.City),
)
country := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.Country),
)
misc := nullable.NewNullableWithValue(
*vo.NewOptionalString127Must(recipient.Misc),
)
companyID := nullable.NewNullNullable[uuid.UUID]()
if recipient.CompanyID != "" {
cid := uuid.MustParse(recipient.CompanyID)
companyID.Set(cid)
}
recipient := model.Recipient{
FirstName: firstName,
LastName: lastName,
Email: email,
Department: department,
Phone: phone,
ExtraIdentifier: extraIdentifier,
Position: position,
City: city,
Country: country,
Misc: misc,
CompanyID: companyID,
}
emailVO := recipient.Email.MustGet()
var companyIDVO *uuid.UUID
if recipient.CompanyID.IsSpecified() && !recipient.CompanyID.IsNull() {
cid := recipient.CompanyID.MustGet()
companyIDVO = &cid
}
r, err := recipientRepository.GetByEmailAndCompanyID(
context.Background(),
&emailVO,
companyIDVO,
)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
if r != nil {
continue
}
id, err := recipientRepository.Insert(
context.Background(),
&recipient,
)
if err != nil {
return errors.Errorf("failed to insert: %s", err)
}
// adding the recipient to the tmpRecpMap
if recipient.CompanyID.IsSpecified() && !recipient.CompanyID.IsNull() {
cid := recipient.CompanyID.MustGet()
cidStr := cid.String()
tmpRecpMap[cidStr] = append(tmpRecpMap[cidStr], id)
}
}
return nil
}