Files
phishingclub/backend/repository/page.go
Ronni Skansing f9365ab299 cleanup from old proxy page test
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
2025-09-30 21:56:44 +02:00

266 lines
5.7 KiB
Go

package repository
import (
"context"
"fmt"
"strings"
"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"
)
var pageAllowedColumns = assignTableToColumns(database.PAGE_TABLE, []string{
"created_at",
"updated_at",
"name",
})
// PageOption is for eager loading
type PageOption struct {
Fields []string
*vo.QueryArgs
WithCompany bool
}
// Page is a Page repository
type Page struct {
DB *gorm.DB
}
// load preloads the table relations
func (pa *Page) load(
options *PageOption,
db *gorm.DB,
) *gorm.DB {
if options.WithCompany {
db = db.Joins("Company")
}
return db
}
// Insert inserts a page
func (pa *Page) Insert(
ctx context.Context,
page *model.Page,
) (*uuid.UUID, error) {
id := uuid.New()
row := page.ToDBMap()
row["id"] = id
AddTimestamps(row)
res := pa.DB.
Model(&database.Page{}).
Create(row)
if res.Error != nil {
return nil, res.Error
}
return &id, nil
}
// GetAll gets pages
func (pa *Page) GetAll(
ctx context.Context,
companyID *uuid.UUID,
options *PageOption,
) (*model.Result[model.Page], error) {
result := model.NewEmptyResult[model.Page]()
var dbPages []database.Page
db := pa.load(options, pa.DB)
db = withCompanyIncludingNullContext(db, companyID, database.PAGE_TABLE)
db, err := useQuery(db, database.PAGE_TABLE, options.QueryArgs, pageAllowedColumns...)
if err != nil {
return result, errs.Wrap(err)
}
if options.Fields != nil {
// TODO potential issue with inner join selects
fields := assignTableToColumns(database.PAGE_TABLE, options.Fields)
db = db.Select(strings.Join(fields, ","))
}
dbRes := db.
Find(&dbPages)
if dbRes.Error != nil {
return result, dbRes.Error
}
hasNextPage, err := useHasNextPage(db, database.PAGE_TABLE, options.QueryArgs, pageAllowedColumns...)
if err != nil {
return result, errs.Wrap(err)
}
result.HasNextPage = hasNextPage
for _, dbPage := range dbPages {
page, err := ToPage(&dbPage)
if err != nil {
return result, errs.Wrap(err)
}
result.Rows = append(result.Rows, page)
}
return result, nil
}
// GetAllByCompanyID gets pages by company id
func (pa *Page) GetAllByCompanyID(
ctx context.Context,
companyID *uuid.UUID,
options *PageOption,
) (*model.Result[model.Page], error) {
result := model.NewEmptyResult[model.Page]()
var dbPages []database.Page
db := pa.load(options, pa.DB)
db = whereCompany(db, database.PAGE_TABLE, companyID)
db, err := useQuery(db, database.PAGE_TABLE, options.QueryArgs, pageAllowedColumns...)
if err != nil {
return result, errs.Wrap(err)
}
if options.Fields != nil {
// TODO potential issue with inner join selects
fields := assignTableToColumns(database.PAGE_TABLE, options.Fields)
db = db.Select(strings.Join(fields, ","))
}
dbRes := db.
Find(&dbPages)
if dbRes.Error != nil {
return result, dbRes.Error
}
hasNextPage, err := useHasNextPage(db, database.PAGE_TABLE, options.QueryArgs, pageAllowedColumns...)
if err != nil {
return result, errs.Wrap(err)
}
result.HasNextPage = hasNextPage
for _, dbPage := range dbPages {
page, err := ToPage(&dbPage)
if err != nil {
return result, errs.Wrap(err)
}
result.Rows = append(result.Rows, page)
}
return result, nil
}
// GetByID gets pages by id
func (pa *Page) GetByID(
ctx context.Context,
id *uuid.UUID,
options *PageOption,
) (*model.Page, error) {
dbPage := database.Page{}
db := pa.load(options, pa.DB)
result := db.
Where(TableColumnID(database.PAGE_TABLE)+" = ?", id).
First(&dbPage)
if result.Error != nil {
return nil, result.Error
}
return ToPage(&dbPage)
}
// GetByCompanyID gets pages by company id
func (pa *Page) GetByCompanyID(
ctx context.Context,
companyID *uuid.UUID,
options *PageOption,
) (*model.Page, error) {
dbPage := database.Page{}
db := pa.load(options, pa.DB)
result := db.
Where(TableColumn(database.PAGE_TABLE, "company_id")+" = ?", companyID).
First(&dbPage)
if result.Error != nil {
return nil, result.Error
}
return ToPage(&dbPage)
}
// GetByNameAndCompanyID gets pages by name
func (pa *Page) GetByNameAndCompanyID(
ctx context.Context,
name *vo.String64,
companyID *uuid.UUID, // can be null
options *PageOption,
) (*model.Page, error) {
page := database.Page{}
db := pa.load(options, pa.DB)
db = withCompanyIncludingNullContext(db, companyID, database.PAGE_TABLE)
result := db.
Where(
fmt.Sprintf(
"%s = ?",
TableColumn(database.PAGE_TABLE, "name"),
),
name.String(),
).
First(&page)
if result.Error != nil {
return nil, result.Error
}
return ToPage(&page)
}
// UpdateByID updates a page by id
func (pa *Page) UpdateByID(
ctx context.Context,
id *uuid.UUID,
page *model.Page,
) error {
row := page.ToDBMap()
AddUpdatedAt(row)
res := pa.DB.
Model(&database.Page{}).
Where("id = ?", id).
Updates(row)
if res.Error != nil {
return res.Error
}
return nil
}
// DeleteByID deletes a page by id
func (l *Page) DeleteByID(
ctx context.Context,
id *uuid.UUID,
) error {
result := l.DB.Delete(&database.Page{}, id)
if result.Error != nil {
return result.Error
}
return nil
}
func ToPage(row *database.Page) (*model.Page, error) {
id := nullable.NewNullableWithValue(*row.ID)
companyID := nullable.NewNullNullable[uuid.UUID]()
if row.CompanyID != nil {
companyID.Set(*row.CompanyID)
}
name := nullable.NewNullableWithValue(*vo.NewString64Must(row.Name))
c, err := vo.NewOptionalString1MB(row.Content)
if err != nil {
return nil, errs.Wrap(err)
}
content := nullable.NewNullableWithValue(*c)
return &model.Page{
ID: id,
CreatedAt: row.CreatedAt,
UpdatedAt: row.UpdatedAt,
CompanyID: companyID,
Name: name,
Content: content,
}, nil
}