mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-31 16:07:22 +02:00
694 lines
18 KiB
Go
694 lines
18 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"slices"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/oapi-codegen/nullable"
|
|
"github.com/phishingclub/phishingclub/database"
|
|
"github.com/phishingclub/phishingclub/errs"
|
|
"github.com/phishingclub/phishingclub/model"
|
|
"github.com/phishingclub/phishingclub/vo"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// IsRecipientInGroup returns true when the given recipient is a member of the given group.
|
|
// uses a COUNT query so it is O(1) regardless of group size.
|
|
func (rg *RecipientGroup) IsRecipientInGroup(
|
|
ctx context.Context,
|
|
groupID *uuid.UUID,
|
|
recipientID *uuid.UUID,
|
|
) (bool, error) {
|
|
var count int64
|
|
res := rg.DB.
|
|
Model(&database.RecipientGroupRecipient{}).
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ? AND %s = ?",
|
|
TableColumn(database.RECIPIENT_GROUP_RECIPIENT_TABLE, "recipient_group_id"),
|
|
TableColumn(database.RECIPIENT_GROUP_RECIPIENT_TABLE, "recipient_id"),
|
|
),
|
|
groupID.String(),
|
|
recipientID.String(),
|
|
).
|
|
Count(&count)
|
|
if res.Error != nil {
|
|
return false, errs.Wrap(res.Error)
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
var RecipientGroupAllowedColumns = assignTableToColumns(database.RECIPIENT_GROUP_TABLE, []string{
|
|
"created_at",
|
|
"updated_at",
|
|
"name",
|
|
})
|
|
|
|
// RecipientGroupOption is a recipient group option
|
|
type RecipientGroupOption struct {
|
|
*vo.QueryArgs
|
|
|
|
WithCompany bool
|
|
WithRecipients bool
|
|
WithRecipientCount bool
|
|
}
|
|
|
|
// RecipientGroup is a recipient group repository
|
|
type RecipientGroup struct {
|
|
DB *gorm.DB
|
|
}
|
|
|
|
// preload loads relational data
|
|
func (rg *RecipientGroup) preload(
|
|
options *RecipientGroupOption,
|
|
db *gorm.DB,
|
|
) *gorm.DB {
|
|
if options.WithCompany {
|
|
db = db.Preload("Company")
|
|
}
|
|
if options.WithRecipients {
|
|
db = db.Preload("Recipients")
|
|
}
|
|
return db
|
|
}
|
|
|
|
// Insert inserts a new recipient group
|
|
func (rg *RecipientGroup) Insert(
|
|
ctx context.Context,
|
|
recipientGroup *model.RecipientGroup,
|
|
) (*uuid.UUID, error) {
|
|
id := uuid.New()
|
|
row := recipientGroup.ToDBMap()
|
|
row["id"] = id
|
|
AddTimestamps(row)
|
|
|
|
res := rg.DB.
|
|
Model(&database.RecipientGroup{}).
|
|
Create(row)
|
|
|
|
if res.Error != nil {
|
|
return nil, res.Error
|
|
}
|
|
return &id, nil
|
|
}
|
|
|
|
// AddRecipients adds recipients to a recipient group
|
|
func (rg *RecipientGroup) AddRecipients(
|
|
ctx context.Context,
|
|
groupID *uuid.UUID,
|
|
recipients []*uuid.UUID,
|
|
) error {
|
|
for _, recipientID := range recipients {
|
|
/* when performing the below optizmie we can handle the whole batch as a single operation...
|
|
batch = append(batch, database.RecipientGroupRecipient{
|
|
RecipientID: recipientID,
|
|
RecipientGroupID: groupID,
|
|
})
|
|
*/
|
|
|
|
var c int64
|
|
// check if the recipient already exists, if so, skip
|
|
res := rg.DB.
|
|
Model(&database.RecipientGroupRecipient{}).
|
|
Where("recipient_id = ? AND recipient_group_id = ?", recipientID, groupID).
|
|
Count(&c)
|
|
|
|
if res.Error != nil {
|
|
return res.Error
|
|
}
|
|
// if already in group, skip it
|
|
if c > 0 {
|
|
continue
|
|
}
|
|
res = rg.DB.
|
|
Model(&database.RecipientGroupRecipient{}).
|
|
Create(&database.RecipientGroupRecipient{
|
|
RecipientID: recipientID,
|
|
RecipientGroupID: groupID,
|
|
})
|
|
if res.Error != nil {
|
|
return res.Error
|
|
}
|
|
}
|
|
|
|
/* TODO OPTIMIZE - This very slow implementation is written like this because it was faster to write
|
|
than it is to setup and handle different databases sqlite, mysql, postgres.
|
|
Optmize this away by checking which db type we are using and using the correct query such as
|
|
IGNORE on mysql and postgres and ON CONFLICT IGNORE on sqlite or something like that..
|
|
*/
|
|
// clause.Insert ignores unique constraint violations so they do not get created, but they do not error
|
|
// does not work in sqlite
|
|
/*
|
|
result := db.Clauses(clause.Insert{Modifier: "OR IGNORE"}).Create(&batch)
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
*/
|
|
|
|
return nil
|
|
}
|
|
|
|
// countRecipients gets the count of recipients in a group.
|
|
// uses the already-loaded group to avoid an extra DB fetch.
|
|
func (rg *RecipientGroup) countRecipients(
|
|
ctx context.Context,
|
|
group *database.RecipientGroup,
|
|
options *RecipientGroupOption,
|
|
) (int64, error) {
|
|
count := model.RECIPIENT_COUNT_NOT_LOADED
|
|
if options.WithRecipientCount {
|
|
// dynamic groups always require a filter query; the junction table is not used
|
|
if group.IsDynamic {
|
|
c, err := rg.countDynamicRecipients(ctx, group)
|
|
if err != nil {
|
|
return count, errs.Wrap(err)
|
|
}
|
|
count = c
|
|
} else if options.WithRecipients {
|
|
// if recipients is loaded then we can get the count from the slice
|
|
count = int64(len(group.Recipients))
|
|
} else {
|
|
// otherwise we need to query the junction table
|
|
c, err := rg.countStaticRecipients(ctx, group.ID)
|
|
if err != nil {
|
|
return count, errs.Wrap(err)
|
|
}
|
|
count = c
|
|
}
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// GetAll gets all recipient groups with pagination
|
|
func (rg *RecipientGroup) GetAll(
|
|
ctx context.Context,
|
|
companyID *uuid.UUID,
|
|
options *RecipientGroupOption,
|
|
) (*model.Result[model.RecipientGroup], error) {
|
|
result := model.NewEmptyResult[model.RecipientGroup]()
|
|
db := rg.preload(options, rg.DB)
|
|
db = withCompanyIncludingNullContext(db, companyID, database.RECIPIENT_GROUP_TABLE)
|
|
db, err := useQuery(
|
|
db,
|
|
database.RECIPIENT_GROUP_TABLE,
|
|
options.QueryArgs,
|
|
RecipientGroupAllowedColumns...,
|
|
)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
|
|
var rows []database.RecipientGroup
|
|
dbRes := db.Find(&rows)
|
|
|
|
if dbRes.Error != nil {
|
|
return result, dbRes.Error
|
|
}
|
|
|
|
hasNextPage, err := useHasNextPage(
|
|
db,
|
|
database.RECIPIENT_GROUP_TABLE,
|
|
options.QueryArgs,
|
|
RecipientGroupAllowedColumns...,
|
|
)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
result.HasNextPage = hasNextPage
|
|
|
|
for _, recipientGroup := range rows {
|
|
count, err := rg.countRecipients(ctx, &recipientGroup, options)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
recipient, err := ToRecipientGroup(&recipientGroup)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
|
|
c := nullable.NewNullNullable[int64]()
|
|
if count != model.RECIPIENT_COUNT_NOT_LOADED {
|
|
c.Set(count)
|
|
}
|
|
recipient.RecipientCount = c
|
|
result.Rows = append(result.Rows, recipient)
|
|
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// GetAllByCompanyID gets all recipient groups with pagination by company ID
|
|
func (rg *RecipientGroup) GetAllByCompanyID(
|
|
ctx context.Context,
|
|
companyID *uuid.UUID,
|
|
options *RecipientGroupOption,
|
|
) ([]*model.RecipientGroup, error) {
|
|
recipientGroups := []*model.RecipientGroup{}
|
|
var rows []database.RecipientGroup
|
|
db := rg.preload(options, rg.DB)
|
|
db = whereCompany(db, database.RECIPIENT_GROUP_TABLE, companyID)
|
|
db, err := useQuery(
|
|
db,
|
|
database.RECIPIENT_GROUP_TABLE,
|
|
options.QueryArgs,
|
|
RecipientGroupAllowedColumns...,
|
|
)
|
|
if err != nil {
|
|
return recipientGroups, errs.Wrap(err)
|
|
}
|
|
result := db.Find(&rows)
|
|
|
|
if result.Error != nil {
|
|
return []*model.RecipientGroup{}, result.Error
|
|
}
|
|
for _, recipientGroup := range rows {
|
|
count, err := rg.countRecipients(ctx, &recipientGroup, options)
|
|
if err != nil {
|
|
return recipientGroups, errs.Wrap(err)
|
|
}
|
|
recipient, err := ToRecipientGroup(&recipientGroup)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
|
|
c := nullable.NewNullNullable[int64]()
|
|
if count != model.RECIPIENT_COUNT_NOT_LOADED {
|
|
c.Set(count)
|
|
}
|
|
recipient.RecipientCount = c
|
|
recipientGroups = append(recipientGroups, recipient)
|
|
|
|
}
|
|
return recipientGroups, nil
|
|
}
|
|
|
|
// GetRecipientCount gets the recipient count of a recipient group.
|
|
// for dynamic groups the count is derived from the filter query; for static groups
|
|
// it counts rows in the junction table.
|
|
func (rg *RecipientGroup) GetRecipientCount(
|
|
ctx context.Context,
|
|
groupID *uuid.UUID,
|
|
) (int64, error) {
|
|
// fetch the group to determine whether it is dynamic
|
|
var group database.RecipientGroup
|
|
res := rg.DB.
|
|
Where(TableColumnID(database.RECIPIENT_GROUP_TABLE)+" = ?", groupID.String()).
|
|
First(&group)
|
|
if res.Error != nil {
|
|
return 0, res.Error
|
|
}
|
|
|
|
if group.IsDynamic {
|
|
return rg.countDynamicRecipients(ctx, &group)
|
|
}
|
|
return rg.countStaticRecipients(ctx, groupID)
|
|
}
|
|
|
|
// countStaticRecipients counts rows in the junction table for a static group
|
|
func (rg *RecipientGroup) countStaticRecipients(
|
|
ctx context.Context,
|
|
groupID *uuid.UUID,
|
|
) (int64, error) {
|
|
var count int64
|
|
result := rg.DB.
|
|
Model(&database.RecipientGroupRecipient{}).
|
|
// active-only count: SCIM-disabled (soft-deleted) members are not counted
|
|
Joins(fmt.Sprintf(
|
|
"JOIN %s ON %s.id = %s.recipient_id AND %s.scim_soft_deleted_at IS NULL",
|
|
database.RECIPIENT_TABLE,
|
|
database.RECIPIENT_TABLE,
|
|
database.RECIPIENT_GROUP_RECIPIENT_TABLE,
|
|
database.RECIPIENT_TABLE,
|
|
)).
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ?",
|
|
TableColumn(database.RECIPIENT_GROUP_RECIPIENT_TABLE, "recipient_group_id"),
|
|
),
|
|
groupID.String(),
|
|
).
|
|
Count(&count)
|
|
if result.Error != nil {
|
|
return 0, result.Error
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// countDynamicRecipients counts recipients that match a dynamic group's filter
|
|
func (rg *RecipientGroup) countDynamicRecipients(
|
|
ctx context.Context,
|
|
group *database.RecipientGroup,
|
|
) (int64, error) {
|
|
if !slices.Contains(model.DynamicGroupAllowedFields, group.FilterField) {
|
|
return 0, fmt.Errorf("invalid filter field: %s", group.FilterField)
|
|
}
|
|
db := rg.DB.Model(&database.Recipient{}).
|
|
Where(fmt.Sprintf("`%s`.`deleted_at` IS NULL", database.RECIPIENT_TABLE)).
|
|
Where(fmt.Sprintf("`%s`.`scim_soft_deleted_at` IS NULL", database.RECIPIENT_TABLE)).
|
|
Where(fmt.Sprintf("`%s`.`%s` = ?", database.RECIPIENT_TABLE, group.FilterField), group.FilterValue)
|
|
db = whereCompany(db, database.RECIPIENT_TABLE, group.CompanyID)
|
|
var count int64
|
|
if err := db.Count(&count).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// GetByID gets a recipient group by id
|
|
func (rg *RecipientGroup) GetByID(
|
|
ctx context.Context,
|
|
id *uuid.UUID,
|
|
options *RecipientGroupOption,
|
|
) (*model.RecipientGroup, error) {
|
|
var rows database.RecipientGroup
|
|
db := rg.preload(options, rg.DB)
|
|
result := db.
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ?",
|
|
TableColumnID(database.RECIPIENT_GROUP_TABLE),
|
|
),
|
|
id.String(),
|
|
).
|
|
First(&rows)
|
|
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
count, err := rg.countRecipients(
|
|
ctx,
|
|
&rows,
|
|
options,
|
|
)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
recipientGroup, err := ToRecipientGroup(&rows)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
c := nullable.NewNullNullable[int64]()
|
|
if count != model.RECIPIENT_COUNT_NOT_LOADED {
|
|
c.Set(count)
|
|
}
|
|
recipientGroup.RecipientCount = c
|
|
return recipientGroup, nil
|
|
}
|
|
|
|
// GetByNameAndCompanyID gets a recipient group by name
|
|
func (rg *RecipientGroup) GetByNameAndCompanyID(
|
|
ctx context.Context,
|
|
name string,
|
|
companyID *uuid.UUID,
|
|
options *RecipientGroupOption,
|
|
) (*model.RecipientGroup, error) {
|
|
var recipientGroup database.RecipientGroup
|
|
db := rg.preload(options, rg.DB)
|
|
whereCompany := fmt.Sprintf(
|
|
"%s IS NULL",
|
|
TableColumn(database.RECIPIENT_GROUP_TABLE, "company_id"),
|
|
)
|
|
if companyID != nil {
|
|
whereCompany = fmt.Sprintf(
|
|
"%s = ?",
|
|
TableColumn(database.RECIPIENT_GROUP_TABLE, "company_id"),
|
|
)
|
|
}
|
|
result := db.
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ? AND %s",
|
|
TableColumnName(database.RECIPIENT_GROUP_TABLE),
|
|
whereCompany,
|
|
),
|
|
name,
|
|
companyID,
|
|
).
|
|
First(&recipientGroup)
|
|
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
count, err := rg.countRecipients(
|
|
ctx,
|
|
&recipientGroup,
|
|
options,
|
|
)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
recpGroup, err := ToRecipientGroup(&recipientGroup)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
c := nullable.NewNullNullable[int64]()
|
|
if count != model.RECIPIENT_COUNT_NOT_LOADED {
|
|
c.Set(count)
|
|
}
|
|
recpGroup.RecipientCount = c
|
|
return recpGroup, nil
|
|
}
|
|
|
|
// GetRecipientsByGroupID gets recipients by recipient group id.
|
|
// for dynamic groups members are resolved by the filter query; for static groups
|
|
// members are fetched from the junction table.
|
|
func (rg *RecipientGroup) GetRecipientsByGroupID(
|
|
ctx context.Context,
|
|
id *uuid.UUID,
|
|
options *RecipientOption,
|
|
) (*model.Result[model.Recipient], error) {
|
|
result := model.NewEmptyResult[model.Recipient]()
|
|
|
|
// fetch the group to determine whether it is dynamic
|
|
var group database.RecipientGroup
|
|
res := rg.DB.
|
|
Where(TableColumnID(database.RECIPIENT_GROUP_TABLE)+" = ?", id.String()).
|
|
First(&group)
|
|
if res.Error != nil {
|
|
return result, res.Error
|
|
}
|
|
|
|
if group.IsDynamic {
|
|
return rg.getDynamicRecipientsByGroup(ctx, &group, options)
|
|
}
|
|
|
|
db := rg.DB
|
|
var recipients []database.Recipient
|
|
if options.WithCompany {
|
|
db = db.Preload("Company")
|
|
}
|
|
db, err := useQuery(db, database.RECIPIENT_TABLE, options.QueryArgs, allowdRecipientColumns...)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
if options.ExcludeSoftDeleted {
|
|
db = db.Where(fmt.Sprintf("`%s`.`scim_soft_deleted_at` IS NULL", database.RECIPIENT_TABLE))
|
|
}
|
|
dbRes := db.
|
|
Model(&database.Recipient{}).
|
|
Joins("JOIN recipient_group_recipients ON recipient_group_recipients.recipient_id = recipients.id").
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ?",
|
|
TableColumn(database.RECIPIENT_GROUP_RECIPIENT_TABLE, "recipient_group_id"),
|
|
),
|
|
id.String(),
|
|
).
|
|
Find(&recipients)
|
|
|
|
if dbRes.Error != nil {
|
|
return result, dbRes.Error
|
|
}
|
|
|
|
hasNextPage, err := useHasNextPage(
|
|
db, database.RECIPIENT_TABLE, options.QueryArgs, allowdRecipientColumns...,
|
|
)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
result.HasNextPage = hasNextPage
|
|
|
|
for _, recipient := range recipients {
|
|
r, err := ToRecipient(&recipient)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
result.Rows = append(result.Rows, r)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// getDynamicRecipientsByGroup resolves members of a dynamic group via its filter
|
|
func (rg *RecipientGroup) getDynamicRecipientsByGroup(
|
|
ctx context.Context,
|
|
group *database.RecipientGroup,
|
|
options *RecipientOption,
|
|
) (*model.Result[model.Recipient], error) {
|
|
result := model.NewEmptyResult[model.Recipient]()
|
|
|
|
if !slices.Contains(model.DynamicGroupAllowedFields, group.FilterField) {
|
|
return result, fmt.Errorf("invalid filter field: %s", group.FilterField)
|
|
}
|
|
|
|
db := rg.DB
|
|
if options.WithCompany {
|
|
db = db.Preload("Company")
|
|
}
|
|
db, err := useQuery(db, database.RECIPIENT_TABLE, options.QueryArgs, allowdRecipientColumns...)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
db = db.Model(&database.Recipient{}).
|
|
Where(fmt.Sprintf("`%s`.`deleted_at` IS NULL", database.RECIPIENT_TABLE)).
|
|
Where(fmt.Sprintf("`%s`.`%s` = ?", database.RECIPIENT_TABLE, group.FilterField), group.FilterValue)
|
|
if options.ExcludeSoftDeleted {
|
|
db = db.Where(fmt.Sprintf("`%s`.`scim_soft_deleted_at` IS NULL", database.RECIPIENT_TABLE))
|
|
}
|
|
db = whereCompany(db, database.RECIPIENT_TABLE, group.CompanyID)
|
|
|
|
var recipients []database.Recipient
|
|
dbRes := db.Find(&recipients)
|
|
if dbRes.Error != nil {
|
|
return result, dbRes.Error
|
|
}
|
|
|
|
hasNextPage, err := useHasNextPage(
|
|
db, database.RECIPIENT_TABLE, options.QueryArgs, allowdRecipientColumns...,
|
|
)
|
|
if err != nil {
|
|
return result, errs.Wrap(err)
|
|
}
|
|
result.HasNextPage = hasNextPage
|
|
|
|
for _, recipient := range recipients {
|
|
r, err := ToRecipient(&recipient)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
result.Rows = append(result.Rows, r)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// UpdateByID updates a recipient group by id
|
|
func (rg *RecipientGroup) UpdateByID(
|
|
ctx context.Context,
|
|
id *uuid.UUID,
|
|
recipientGroup *model.RecipientGroup,
|
|
) error {
|
|
row := recipientGroup.ToDBMap()
|
|
AddUpdatedAt(row)
|
|
res := rg.DB.
|
|
Model(&database.RecipientGroup{}).
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ?",
|
|
TableColumnID(database.RECIPIENT_GROUP_TABLE),
|
|
),
|
|
id.String(),
|
|
).
|
|
Updates(row)
|
|
|
|
if res.Error != nil {
|
|
return res.Error
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RemoveRecipientByIDFromAllGroups removes a recipient from all recipient groups
|
|
func (rg *RecipientGroup) RemoveRecipientByIDFromAllGroups(
|
|
ctx context.Context,
|
|
recipientID *uuid.UUID,
|
|
) error {
|
|
result := rg.DB.
|
|
Where(
|
|
fmt.Sprintf(
|
|
"%s = ?",
|
|
TableColumn(database.RECIPIENT_GROUP_RECIPIENT_TABLE, "recipient_id"),
|
|
),
|
|
recipientID.String(),
|
|
).
|
|
Delete(&database.RecipientGroupRecipient{})
|
|
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RemoveRecipients removes a recipient from a recipient group
|
|
func (rg *RecipientGroup) RemoveRecipients(
|
|
ctx context.Context,
|
|
groupID *uuid.UUID,
|
|
recipientIDs []*uuid.UUID,
|
|
) error {
|
|
result := rg.DB.
|
|
Where("recipient_group_id = ? AND recipient_id IN ?", groupID, recipientIDs).
|
|
Delete(&database.RecipientGroupRecipient{})
|
|
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DeleteByID deletes a recipient group by id
|
|
func (rg *RecipientGroup) DeleteByID(
|
|
ctx context.Context,
|
|
id *uuid.UUID,
|
|
) error {
|
|
// delete recipients
|
|
res := rg.DB.
|
|
Where("recipient_group_id = ?", id).
|
|
Delete(&database.RecipientGroupRecipient{})
|
|
|
|
if res.Error != nil {
|
|
return res.Error
|
|
}
|
|
// delete recipient group
|
|
res = rg.DB.
|
|
Where("id = ?", id).
|
|
Delete(&database.RecipientGroup{})
|
|
|
|
if res.Error != nil {
|
|
return res.Error
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ToRecipientGroup converts a database row to a model
|
|
func ToRecipientGroup(row *database.RecipientGroup) (*model.RecipientGroup, error) {
|
|
id := nullable.NewNullableWithValue(*row.ID)
|
|
companyID := nullable.NewNullNullable[uuid.UUID]()
|
|
if row.CompanyID != nil {
|
|
companyID.Set(*row.CompanyID)
|
|
}
|
|
name := nullable.NewNullableWithValue(*vo.NewString127Must(row.Name))
|
|
recipients := []*model.Recipient{}
|
|
if len(row.Recipients) > 0 {
|
|
for _, recipient := range row.Recipients {
|
|
r, err := ToRecipient(&recipient)
|
|
if err != nil {
|
|
return nil, errs.Wrap(err)
|
|
}
|
|
recipients = append(recipients, r)
|
|
}
|
|
}
|
|
|
|
return &model.RecipientGroup{
|
|
ID: id,
|
|
CreatedAt: row.CreatedAt,
|
|
UpdatedAt: row.UpdatedAt,
|
|
Name: name,
|
|
CompanyID: companyID,
|
|
IsDynamic: nullable.NewNullableWithValue(row.IsDynamic),
|
|
FilterField: nullable.NewNullableWithValue(row.FilterField),
|
|
FilterValue: nullable.NewNullableWithValue(row.FilterValue),
|
|
Recipients: recipients,
|
|
RecipientCount: nullable.NewNullNullable[int64](),
|
|
}, nil
|
|
}
|