mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-02-12 16:12:44 +00:00
245 lines
7.9 KiB
Go
245 lines
7.9 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/go-errors/errors"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/oapi-codegen/nullable"
|
|
"github.com/phishingclub/phishingclub/errs"
|
|
"github.com/phishingclub/phishingclub/validate"
|
|
"github.com/phishingclub/phishingclub/vo"
|
|
)
|
|
|
|
type Domain struct {
|
|
ID nullable.Nullable[uuid.UUID] `json:"id"`
|
|
CreatedAt *time.Time `json:"createdAt"`
|
|
UpdatedAt *time.Time `json:"updatedAt"`
|
|
Name nullable.Nullable[vo.String255] `json:"name"`
|
|
Type nullable.Nullable[vo.String32] `json:"type"` // "regular" or "proxy"
|
|
ProxyTargetDomain nullable.Nullable[vo.OptionalString255] `json:"proxyTargetDomain"` // target URL for proxy (can be full URL or domain)
|
|
HostWebsite nullable.Nullable[bool] `json:"hostWebsite"`
|
|
ManagedTLS nullable.Nullable[bool] `json:"managedTLS"`
|
|
OwnManagedTLS nullable.Nullable[bool] `json:"ownManagedTLS"`
|
|
SelfSignedTLS nullable.Nullable[bool] `json:"selfSignedTLS"`
|
|
// private key
|
|
OwnManagedTLSKey nullable.Nullable[string] `json:"ownManagedTLSKey"`
|
|
// cert
|
|
OwnManagedTLSPem nullable.Nullable[string] `json:"ownManagedTLSPem"`
|
|
PageContent nullable.Nullable[vo.OptionalString1MB] `json:"pageContent"`
|
|
PageNotFoundContent nullable.Nullable[vo.OptionalString1MB] `json:"pageNotFoundContent"`
|
|
RedirectURL nullable.Nullable[vo.OptionalString1024] `json:"redirectURL"`
|
|
CompanyID nullable.Nullable[uuid.UUID] `json:"companyID"`
|
|
ProxyID nullable.Nullable[uuid.UUID] `json:"proxyID"`
|
|
Company *Company `json:"company"`
|
|
}
|
|
|
|
// Validate checks if the Domain configuration with a valid state
|
|
func (d *Domain) Validate() error {
|
|
if err := validate.NullableFieldRequired("name", d.Name); err != nil {
|
|
return err
|
|
}
|
|
|
|
// set default type if not specified
|
|
if !d.Type.IsSpecified() {
|
|
d.Type.Set(*vo.NewString32Must("regular"))
|
|
}
|
|
|
|
domainType, err := d.Type.Get()
|
|
if err != nil {
|
|
return validate.WrapErrorWithField(errors.New("type is required"), "type")
|
|
}
|
|
|
|
// validate type is either "regular" or "proxy"
|
|
if domainType.String() != "regular" && domainType.String() != "proxy" {
|
|
return validate.WrapErrorWithField(errors.New("type must be 'regular' or 'proxy'"), "type")
|
|
}
|
|
|
|
if domainType.String() == "proxy" {
|
|
// proxy domains require proxyTargetDomain
|
|
if err := validate.NullableFieldRequired("proxyTargetDomain", d.ProxyTargetDomain); err != nil {
|
|
return err
|
|
}
|
|
// proxy domains don't need page content validation
|
|
} else {
|
|
// regular domains need standard validation
|
|
if err := validate.NullableFieldRequired("hostWebsite", d.HostWebsite); err != nil {
|
|
return err
|
|
}
|
|
if err := validate.NullableFieldRequired("managedTLS", d.ManagedTLS); err != nil {
|
|
return err
|
|
}
|
|
if err := validate.NullableFieldRequired("pageContent", d.PageContent); err != nil {
|
|
return err
|
|
}
|
|
if err := validate.NullableFieldRequired("pageNotFoundContent", d.PageNotFoundContent); err != nil {
|
|
return err
|
|
}
|
|
if err := validate.NullableFieldRequired("redirectURL", d.RedirectURL); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
//
|
|
//
|
|
ownManagedTLS, err := d.OwnManagedTLS.Get()
|
|
ownManagedTLSSet := err == nil && ownManagedTLS
|
|
|
|
selfSignedTLS, err := d.SelfSignedTLS.Get()
|
|
selfSignedTLSSet := err == nil && selfSignedTLS
|
|
|
|
managedTLS, err := d.ManagedTLS.Get()
|
|
managedTLSSet := err == nil && managedTLS
|
|
|
|
// count how many TLS options are enabled
|
|
tlsCount := 0
|
|
if managedTLSSet {
|
|
tlsCount++
|
|
}
|
|
if ownManagedTLSSet {
|
|
tlsCount++
|
|
}
|
|
if selfSignedTLSSet {
|
|
tlsCount++
|
|
}
|
|
|
|
// only one TLS option can be enabled at a time
|
|
if tlsCount > 1 {
|
|
return errs.NewValidationError(errors.New(
|
|
"Domain TLS can only have one option enabled: managed, own managed, or self-signed",
|
|
))
|
|
}
|
|
if ownManagedTLS {
|
|
// handle own managed ManagedTLS
|
|
ownManagedTLSKey, err := d.OwnManagedTLSKey.Get()
|
|
ownManagedTLSPem, err := d.OwnManagedTLSPem.Get()
|
|
ownManagedTLSKeyIsSet := err == nil && len(ownManagedTLSKey) > 0
|
|
ownManagedTLSPemIsSet := err == nil && len(ownManagedTLSPem) > 0
|
|
// both must be set, not one of
|
|
if (ownManagedTLSKeyIsSet && !ownManagedTLSPemIsSet) ||
|
|
(!ownManagedTLSKeyIsSet && ownManagedTLSPemIsSet) {
|
|
return errs.NewValidationError(errors.New(
|
|
"Own managed TLS requires a private key (.key) and a certificate (.pem)",
|
|
))
|
|
}
|
|
}
|
|
/*
|
|
// TODO hostWebsite vs redirectURL are mutually exclusive
|
|
hostWebsite := d.HostWebsite.MustGet()
|
|
redirectURL := d.RedirectURL.MustGet()
|
|
redirectURLLen := len(redirectURL.String())
|
|
if hostWebsite && redirectURLLen > 0 {
|
|
return validate.WrapErrorWithField(
|
|
errors.New("both can not be set"),
|
|
"Host website and redirect url",
|
|
)
|
|
} */
|
|
return nil
|
|
}
|
|
|
|
// ToDBMap converts the fields that can be stored or updated to a map
|
|
// if the value is nullable and not set, it is not included
|
|
// if the value is nullable and set, it is included, if it is null, it is set to nil
|
|
func (d *Domain) ToDBMap() map[string]any {
|
|
m := map[string]any{}
|
|
if d.Name.IsSpecified() {
|
|
m["name"] = nil
|
|
if name, err := d.Name.Get(); err == nil {
|
|
m["name"] = name.String()
|
|
}
|
|
}
|
|
if d.Type.IsSpecified() {
|
|
m["type"] = "regular"
|
|
if domainType, err := d.Type.Get(); err == nil {
|
|
m["type"] = domainType.String()
|
|
}
|
|
}
|
|
if d.ProxyTargetDomain.IsSpecified() {
|
|
m["proxy_target_domain"] = nil
|
|
if proxyTargetDomain, err := d.ProxyTargetDomain.Get(); err == nil {
|
|
m["proxy_target_domain"] = proxyTargetDomain.String()
|
|
}
|
|
}
|
|
if d.HostWebsite.IsSpecified() {
|
|
m["host_website"] = nil
|
|
if hostWebsite, err := d.HostWebsite.Get(); err == nil {
|
|
m["host_website"] = hostWebsite
|
|
}
|
|
m["redirect_url"] = ""
|
|
}
|
|
if d.RedirectURL.IsSpecified() {
|
|
m["redirect_url"] = nil
|
|
if redirectURL, err := d.RedirectURL.Get(); err == nil {
|
|
m["redirect_url"] = redirectURL.String()
|
|
}
|
|
}
|
|
if d.PageContent.IsSpecified() {
|
|
m["page_content"] = nil
|
|
if staticPage, err := d.PageContent.Get(); err == nil {
|
|
m["page_content"] = staticPage.String()
|
|
}
|
|
}
|
|
if d.PageNotFoundContent.IsSpecified() {
|
|
m["page_not_found_content"] = nil
|
|
if staticNotFound, err := d.PageNotFoundContent.Get(); err == nil {
|
|
m["page_not_found_content"] = staticNotFound.String()
|
|
}
|
|
}
|
|
if d.CompanyID.IsSpecified() {
|
|
if d.CompanyID.IsNull() {
|
|
m["company_id"] = nil
|
|
} else {
|
|
m["company_id"] = d.CompanyID.MustGet()
|
|
}
|
|
}
|
|
if d.ManagedTLS.IsSpecified() {
|
|
m["managed_tls_certs"] = false
|
|
if d.ManagedTLS.IsNull() {
|
|
m["managed_tls_certs"] = nil
|
|
} else {
|
|
m["managed_tls_certs"] = d.ManagedTLS.MustGet()
|
|
}
|
|
}
|
|
if d.OwnManagedTLS.IsSpecified() {
|
|
m["own_managed_tls"] = false
|
|
if d.OwnManagedTLS.IsNull() {
|
|
m["own_managed_tls"] = nil
|
|
} else {
|
|
m["own_managed_tls"] = d.OwnManagedTLS.MustGet()
|
|
}
|
|
}
|
|
if d.SelfSignedTLS.IsSpecified() {
|
|
m["self_signed_tls"] = false
|
|
if d.SelfSignedTLS.IsNull() {
|
|
m["self_signed_tls"] = nil
|
|
} else {
|
|
m["self_signed_tls"] = d.SelfSignedTLS.MustGet()
|
|
}
|
|
}
|
|
if d.ProxyID.IsSpecified() {
|
|
if d.ProxyID.IsNull() {
|
|
m["proxy_id"] = nil
|
|
} else {
|
|
m["proxy_id"] = d.ProxyID.MustGet()
|
|
}
|
|
}
|
|
return m
|
|
}
|
|
|
|
// DomainOverview is a subset of the domain as used as read-only
|
|
type DomainOverview struct {
|
|
ID uuid.UUID `json:"id,omitempty"`
|
|
CreatedAt *time.Time `json:"createdAt"`
|
|
UpdatedAt *time.Time `json:"updatedAt"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
ProxyTargetDomain string `json:"proxyTargetDomain"`
|
|
HostWebsite bool `json:"hostWebsite"`
|
|
ManagedTLS bool `json:"managedTLS"`
|
|
OwnManagedTLS bool `json:"ownManagedTLS"`
|
|
SelfSignedTLS bool `json:"selfSignedTLS"`
|
|
RedirectURL string `json:"redirectURL"`
|
|
CompanyID *uuid.UUID `json:"companyID"`
|
|
ProxyID *uuid.UUID `json:"proxyID"`
|
|
}
|