Rename external URLs and move profile fields

Rename the compliance external URL concept to compliance custom links,
and move the public-facing profile fields (description, website, email,
headquarter address) off the organization onto the trust center. Backfill
managed default domains for pages that lack them.

Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-07-10 15:11:40 +02:00
parent b524e9b497
commit 55a8e72c17
9 changed files with 239 additions and 215 deletions

View File

@@ -105,8 +105,8 @@ func ResourceTypeName(entityType uint16) string {
return "WebhookSubscription"
case ComplianceFrameworkEntityType:
return "ComplianceFramework"
case ComplianceExternalURLEntityType:
return "ComplianceExternalURL"
case ComplianceCustomLinkEntityType:
return "ComplianceCustomLink"
case MailingListEntityType:
return "MailingList"
case MailingListSubscriberEntityType:

View File

@@ -35,7 +35,7 @@ import (
)
type (
ComplianceExternalURL struct {
ComplianceCustomLink struct {
ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"`
TrustCenterID gid.GID `db:"trust_center_id"`
@@ -46,26 +46,26 @@ type (
UpdatedAt time.Time `db:"updated_at"`
}
ComplianceExternalURLs []*ComplianceExternalURL
ComplianceCustomLinks []*ComplianceCustomLink
)
func (c ComplianceExternalURL) CursorKey(orderBy ComplianceExternalURLOrderField) page.CursorKey {
func (c ComplianceCustomLink) CursorKey(orderBy ComplianceCustomLinkOrderField) page.CursorKey {
switch orderBy {
case ComplianceExternalURLOrderFieldCreatedAt:
case ComplianceCustomLinkOrderFieldCreatedAt:
return page.NewCursorKey(c.ID, c.CreatedAt)
case ComplianceExternalURLOrderFieldRank:
case ComplianceCustomLinkOrderFieldRank:
return page.NewCursorKey(c.ID, c.Rank)
}
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (c *ComplianceExternalURL) AuthorizationAttributes(
func (c *ComplianceCustomLink) AuthorizationAttributes(
ctx context.Context,
conn pg.Querier,
resourceIDs []gid.GID,
) (policy.AttributesByID, error) {
q := `SELECT id, organization_id FROM compliance_external_urls WHERE id = ANY(@resource_ids::text[])`
q := `SELECT id, organization_id FROM compliance_custom_links WHERE id = ANY(@resource_ids::text[])`
args := pgx.StrictNamedArgs{
"resource_ids": resourceIDs,
@@ -99,7 +99,7 @@ func (c *ComplianceExternalURL) AuthorizationAttributes(
return attrsByID, nil
}
func (c *ComplianceExternalURL) LoadByID(
func (c *ComplianceCustomLink) LoadByID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
@@ -116,7 +116,7 @@ SELECT
created_at,
updated_at
FROM
compliance_external_urls
compliance_custom_links
WHERE
%s
AND id = @id
@@ -129,16 +129,16 @@ LIMIT 1;
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query compliance_external_urls: %w", err)
return fmt.Errorf("cannot query compliance_custom_links: %w", err)
}
result, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ComplianceExternalURL])
result, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ComplianceCustomLink])
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return ErrResourceNotFound
}
return fmt.Errorf("cannot collect compliance external URL: %w", err)
return fmt.Errorf("cannot collect compliance custom link: %w", err)
}
*c = result
@@ -146,14 +146,14 @@ LIMIT 1;
return nil
}
func (c *ComplianceExternalURL) Insert(
func (c *ComplianceCustomLink) Insert(
ctx context.Context,
conn pg.Tx,
scope Scoper,
) error {
q := `
INSERT INTO
compliance_external_urls (
compliance_custom_links (
id,
tenant_id,
organization_id,
@@ -171,7 +171,7 @@ VALUES (
@trust_center_id,
@name,
@url,
(SELECT COALESCE(MAX(rank), 0) + 1 FROM compliance_external_urls WHERE trust_center_id = @trust_center_id),
(SELECT COALESCE(MAX(rank), 0) + 1 FROM compliance_custom_links WHERE trust_center_id = @trust_center_id),
@created_at,
@updated_at
)
@@ -190,19 +190,19 @@ RETURNING rank;
}
if err := conn.QueryRow(ctx, q, args).Scan(&c.Rank); err != nil {
return fmt.Errorf("cannot insert compliance external URL: %w", err)
return fmt.Errorf("cannot insert compliance custom link: %w", err)
}
return nil
}
func (c *ComplianceExternalURL) Update(
func (c *ComplianceCustomLink) Update(
ctx context.Context,
conn pg.Tx,
scope Scoper,
) error {
q := `
UPDATE compliance_external_urls
UPDATE compliance_custom_links
SET
name = @name,
url = @url,
@@ -223,13 +223,13 @@ WHERE
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot update compliance external URL: %w", err)
return fmt.Errorf("cannot update compliance custom link: %w", err)
}
return nil
}
func (c *ComplianceExternalURL) UpdateRank(
func (c *ComplianceCustomLink) UpdateRank(
ctx context.Context,
conn pg.Tx,
scope Scoper,
@@ -238,11 +238,11 @@ func (c *ComplianceExternalURL) UpdateRank(
WITH old AS (
SELECT
rank AS old_rank
FROM compliance_external_urls
FROM compliance_custom_links
WHERE %s AND id = @id AND trust_center_id = @trust_center_id
)
UPDATE compliance_external_urls
UPDATE compliance_custom_links
SET
rank = CASE
WHEN id = @id THEN @new_rank
@@ -274,20 +274,20 @@ WHERE %s
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot update compliance external URL rank: %w", err)
return fmt.Errorf("cannot update compliance custom link rank: %w", err)
}
return nil
}
func (c *ComplianceExternalURL) Delete(
func (c *ComplianceCustomLink) Delete(
ctx context.Context,
conn pg.Tx,
scope Scoper,
) error {
q := `
DELETE FROM
compliance_external_urls
compliance_custom_links
WHERE
%s
AND id = @id;
@@ -299,18 +299,18 @@ WHERE
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot delete compliance external URL: %w", err)
return fmt.Errorf("cannot delete compliance custom link: %w", err)
}
return nil
}
func (c *ComplianceExternalURLs) LoadByTrustCenterID(
func (c *ComplianceCustomLinks) LoadByTrustCenterID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
trustCenterID gid.GID,
cursor *page.Cursor[ComplianceExternalURLOrderField],
cursor *page.Cursor[ComplianceCustomLinkOrderField],
) error {
q := `
SELECT
@@ -323,7 +323,7 @@ SELECT
created_at,
updated_at
FROM
compliance_external_urls
compliance_custom_links
WHERE
%s
AND trust_center_id = @trust_center_id
@@ -337,12 +337,12 @@ WHERE
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query compliance_external_urls: %w", err)
return fmt.Errorf("cannot query compliance_custom_links: %w", err)
}
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ComplianceExternalURL])
results, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ComplianceCustomLink])
if err != nil {
return fmt.Errorf("cannot collect compliance external URLs: %w", err)
return fmt.Errorf("cannot collect compliance custom links: %w", err)
}
*c = results

View File

@@ -28,51 +28,51 @@ import (
)
type (
ComplianceExternalURLOrderField string
ComplianceCustomLinkOrderField string
)
const (
ComplianceExternalURLOrderFieldCreatedAt ComplianceExternalURLOrderField = "CREATED_AT"
ComplianceExternalURLOrderFieldRank ComplianceExternalURLOrderField = "RANK"
ComplianceCustomLinkOrderFieldCreatedAt ComplianceCustomLinkOrderField = "CREATED_AT"
ComplianceCustomLinkOrderFieldRank ComplianceCustomLinkOrderField = "RANK"
)
var (
_ page.OrderField = ComplianceExternalURLOrderField("")
_ fmt.Stringer = ComplianceExternalURLOrderField("")
_ encoding.TextMarshaler = ComplianceExternalURLOrderField("")
_ encoding.TextUnmarshaler = (*ComplianceExternalURLOrderField)(nil)
_ page.OrderField = ComplianceCustomLinkOrderField("")
_ fmt.Stringer = ComplianceCustomLinkOrderField("")
_ encoding.TextMarshaler = ComplianceCustomLinkOrderField("")
_ encoding.TextUnmarshaler = (*ComplianceCustomLinkOrderField)(nil)
)
func ComplianceExternalURLOrderFields() []ComplianceExternalURLOrderField {
return []ComplianceExternalURLOrderField{
ComplianceExternalURLOrderFieldCreatedAt,
ComplianceExternalURLOrderFieldRank,
func ComplianceCustomLinkOrderFields() []ComplianceCustomLinkOrderField {
return []ComplianceCustomLinkOrderField{
ComplianceCustomLinkOrderFieldCreatedAt,
ComplianceCustomLinkOrderFieldRank,
}
}
func (v ComplianceExternalURLOrderField) IsValid() bool {
func (v ComplianceCustomLinkOrderField) IsValid() bool {
switch v {
case
ComplianceExternalURLOrderFieldCreatedAt,
ComplianceExternalURLOrderFieldRank:
ComplianceCustomLinkOrderFieldCreatedAt,
ComplianceCustomLinkOrderFieldRank:
return true
}
return false
}
func (v ComplianceExternalURLOrderField) String() string {
func (v ComplianceCustomLinkOrderField) String() string {
return string(v)
}
func (v ComplianceExternalURLOrderField) MarshalText() ([]byte, error) {
func (v ComplianceCustomLinkOrderField) MarshalText() ([]byte, error) {
return []byte(v.String()), nil
}
func (v *ComplianceExternalURLOrderField) UnmarshalText(text []byte) error {
val := ComplianceExternalURLOrderField(text)
func (v *ComplianceCustomLinkOrderField) UnmarshalText(text []byte) error {
val := ComplianceCustomLinkOrderField(text)
if !val.IsValid() {
return fmt.Errorf("invalid ComplianceExternalURLOrderField value: %q", string(text))
return fmt.Errorf("invalid ComplianceCustomLinkOrderField value: %q", string(text))
}
*v = val
@@ -80,11 +80,11 @@ func (v *ComplianceExternalURLOrderField) UnmarshalText(text []byte) error {
return nil
}
func (p ComplianceExternalURLOrderField) Column() string {
func (p ComplianceCustomLinkOrderField) Column() string {
switch p {
case ComplianceExternalURLOrderFieldCreatedAt:
case ComplianceCustomLinkOrderFieldCreatedAt:
return "created_at"
case ComplianceExternalURLOrderFieldRank:
case ComplianceCustomLinkOrderFieldRank:
return "rank"
default:
return string(p)

View File

@@ -0,0 +1,19 @@
-- Copyright (c) 2026 Probo Inc <hello@probo.com>.
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted, provided that the above
-- copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
ALTER TABLE compliance_external_urls RENAME TO compliance_custom_links;
ALTER TABLE compliance_custom_links
RENAME CONSTRAINT compliance_external_urls_trust_center_id_rank_key
TO compliance_custom_links_trust_center_id_rank_key;

View File

@@ -0,0 +1,34 @@
-- Copyright (c) 2026 Probo Inc <hello@probo.com>.
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted, provided that the above
-- copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
ALTER TABLE trust_centers
ADD COLUMN description TEXT,
ADD COLUMN website_url TEXT,
ADD COLUMN email CITEXT,
ADD COLUMN headquarter_address TEXT;
UPDATE trust_centers tc
SET
description = o.description,
website_url = o.website_url,
email = o.email,
headquarter_address = o.headquarter_address
FROM organizations o
WHERE tc.organization_id = o.id;
ALTER TABLE organizations
DROP COLUMN description,
DROP COLUMN website_url,
DROP COLUMN email,
DROP COLUMN headquarter_address;

View File

@@ -0,0 +1,107 @@
-- Copyright (c) 2026 Probo Inc <hello@probo.com>.
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted, provided that the above
-- copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
-- Backfill managed default domains for compliance pages created before
-- default-domain provisioning existed. Hostnames use the managed base domain
-- suffix configured on the database (probo.trust_center_base_domain), falling
-- back to probopage.com for production installs.
WITH pending_pages AS (
SELECT
tc.id AS trust_center_id,
tc.tenant_id,
tc.organization_id,
tc.slug,
tc.created_at,
(
tc.slug || '.' || COALESCE(
NULLIF(current_setting('probo.trust_center_base_domain', true), ''),
'probopage.com'
)
)::citext AS hostname
FROM trust_centers tc
WHERE tc.default_domain_id IS NULL
),
minted_certificates AS (
INSERT INTO certificates (
id,
tenant_id,
hostname,
status,
ssl_retry_count,
created_at,
updated_at
)
SELECT
translate(
encode(
substring(decode(translate(pp.trust_center_id, '-_', '+/'), 'base64') FROM 1 FOR 8)
|| int2send(104::smallint)
|| int8send((floor(extract(epoch FROM clock_timestamp()) * 1000))::bigint)
|| substring(decode(md5(random()::text || pp.trust_center_id), 'hex') FROM 1 FOR 6),
'base64'
),
'+/',
'-_'
),
pp.tenant_id,
pp.hostname,
'PENDING'::custom_domain_ssl_status,
0,
pp.created_at,
clock_timestamp()
FROM pending_pages pp
RETURNING id, hostname, tenant_id
),
minted_domains AS (
INSERT INTO custom_domains (
id,
tenant_id,
organization_id,
domain,
managed,
certificate_id,
created_at,
updated_at
)
SELECT
translate(
encode(
substring(decode(translate(mc.id, '-_', '+/'), 'base64') FROM 1 FOR 8)
|| int2send(37::smallint)
|| int8send((floor(extract(epoch FROM clock_timestamp()) * 1000))::bigint)
|| substring(decode(md5(random()::text || mc.id), 'hex') FROM 1 FOR 6),
'base64'
),
'+/',
'-_'
),
mc.tenant_id,
pp.organization_id,
pp.hostname,
true,
mc.id,
pp.created_at,
clock_timestamp()
FROM minted_certificates mc
JOIN pending_pages pp ON pp.hostname = mc.hostname
RETURNING id, domain
)
UPDATE trust_centers tc
SET
default_domain_id = md.id,
updated_at = clock_timestamp()
FROM minted_domains md
JOIN pending_pages pp ON pp.hostname = md.domain
WHERE tc.id = pp.trust_center_id;

View File

@@ -41,11 +41,6 @@ type (
Name string `db:"name"`
LogoFileID *gid.GID `db:"logo_file_id"`
HorizontalLogoFileID *gid.GID `db:"horizontal_logo_file_id"`
Description *string `db:"description"`
WebsiteURL *string `db:"website_url"`
Email *string `db:"email"`
HeadquarterAddress *string `db:"headquarter_address"`
CustomDomainID *gid.GID `db:"custom_domain_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
@@ -117,11 +112,6 @@ SELECT
name,
logo_file_id,
horizontal_logo_file_id,
description,
website_url,
email,
headquarter_address,
custom_domain_id,
created_at,
updated_at
FROM
@@ -169,11 +159,6 @@ SELECT
name,
logo_file_id,
horizontal_logo_file_id,
description,
website_url,
email,
headquarter_address,
custom_domain_id,
created_at,
updated_at
FROM
@@ -229,11 +214,6 @@ SELECT
name,
logo_file_id,
horizontal_logo_file_id,
description,
website_url,
email,
headquarter_address,
custom_domain_id,
created_at,
updated_at
FROM
@@ -290,11 +270,6 @@ SELECT
name,
logo_file_id,
horizontal_logo_file_id,
description,
website_url,
email,
headquarter_address,
custom_domain_id,
created_at,
updated_at
FROM
@@ -338,14 +313,9 @@ INSERT INTO organizations (
name,
logo_file_id,
horizontal_logo_file_id,
description,
website_url,
email,
headquarter_address,
custom_domain_id,
created_at,
updated_at
) VALUES (@tenant_id, @id, @name, @logo_file_id, @horizontal_logo_file_id, @description, @website_url, @email, @headquarter_address, @custom_domain_id, @created_at, @updated_at)
) VALUES (@tenant_id, @id, @name, @logo_file_id, @horizontal_logo_file_id, @created_at, @updated_at)
`
args := pgx.StrictNamedArgs{
@@ -354,11 +324,6 @@ INSERT INTO organizations (
"name": o.Name,
"logo_file_id": o.LogoFileID,
"horizontal_logo_file_id": o.HorizontalLogoFileID,
"description": o.Description,
"website_url": o.WebsiteURL,
"email": o.Email,
"headquarter_address": o.HeadquarterAddress,
"custom_domain_id": o.CustomDomainID,
"created_at": o.CreatedAt,
"updated_at": o.UpdatedAt,
}
@@ -382,11 +347,6 @@ SET
name = @name,
logo_file_id = @logo_file_id,
horizontal_logo_file_id = @horizontal_logo_file_id,
description = @description,
website_url = @website_url,
email = @email,
headquarter_address = @headquarter_address,
custom_domain_id = @custom_domain_id,
updated_at = @updated_at
WHERE
%s
@@ -400,11 +360,6 @@ WHERE
"name": o.Name,
"logo_file_id": o.LogoFileID,
"horizontal_logo_file_id": o.HorizontalLogoFileID,
"description": o.Description,
"website_url": o.WebsiteURL,
"email": o.Email,
"headquarter_address": o.HeadquarterAddress,
"custom_domain_id": o.CustomDomainID,
"updated_at": o.UpdatedAt,
}
@@ -437,55 +392,3 @@ WHERE id = @id
return nil
}
func (o *Organization) LoadByCustomDomainID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
customDomainID gid.GID,
) error {
q := `
SELECT
tenant_id,
id,
name,
logo_file_id,
horizontal_logo_file_id,
description,
website_url,
email,
headquarter_address,
custom_domain_id,
created_at,
updated_at
FROM
organizations
WHERE
%s
AND custom_domain_id = @custom_domain_id
LIMIT 1
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"custom_domain_id": customDomainID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query organization by custom domain: %w", err)
}
organization, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Organization])
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return ErrResourceNotFound
}
return fmt.Errorf("cannot collect organization: %w", err)
}
*o = organization
return nil
}

View File

@@ -69,10 +69,6 @@ type (
Name *string
LogoFile *UploadedFile
HorizontalLogoFile *UploadedFile
Description **string
WebsiteURL **string
Email **string
HeadquarterAddress **string
}
CreateSAMLConfigurationRequest struct {
@@ -191,10 +187,6 @@ func (req UpdateOrganizationRequest) Validate() error {
fv := filevalidation.NewValidator(filevalidation.WithCategories(filevalidation.CategoryImage))
v.Check(req.Name, "name", validator.SafeTextNoNewLine(255))
v.Check(req.Description, "description", validator.SafeText(ContentMaxLength))
v.Check(req.WebsiteURL, "website_url", validator.SafeText(2048))
v.Check(req.Email, "email", validator.SafeText(255))
v.Check(req.HeadquarterAddress, "headquarter_address", validator.SafeText(2048))
v.Check(req.LogoFile, "logo_file", validator.NotEmpty())
if req.LogoFile != nil {
@@ -763,6 +755,28 @@ func (s *OrganizationService) CreateOrganization(
return fmt.Errorf("cannot insert mailing list: %w", err)
}
defaultDomainHostname := trustCenter.Slug + "." + s.trustCenterBaseDomain
defaultDomain := coredata.NewCustomDomain(
tenantID,
organization.ID,
defaultDomainHostname,
true,
)
certificate, err := s.certManager.EnsureCertificate(ctx, tx, scope, defaultDomainHostname)
if err != nil {
return fmt.Errorf("cannot ensure certificate for default custom domain: %w", err)
}
defaultDomain.CertificateID = &certificate.ID
if err := defaultDomain.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert default custom domain: %w", err)
}
trustCenter.DefaultDomainID = &defaultDomain.ID
if err := trustCenter.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert trust center: %w", err)
}
@@ -905,28 +919,6 @@ func (s *OrganizationService) UpdateOrganization(ctx context.Context, organizati
organization.Name = *req.Name
}
if req.Description != nil {
organization.Description = *req.Description
}
if req.WebsiteURL != nil {
organization.WebsiteURL = *req.WebsiteURL
}
if req.Email != nil {
if *req.Email != nil {
if _, err := mail.ParseAddr(**req.Email); err != nil {
return fmt.Errorf("invalid email address: %w", err)
}
}
organization.Email = *req.Email
}
if req.HeadquarterAddress != nil {
organization.HeadquarterAddress = *req.HeadquarterAddress
}
if logoFile != nil {
if err := logoFile.Insert(ctx, tx, scope); err != nil {
return fmt.Errorf("cannot insert file: %w", err)

View File

@@ -25,7 +25,6 @@ import (
"errors"
"fmt"
"mime"
"net/mail"
"path/filepath"
"time"
@@ -49,10 +48,6 @@ type (
Name *string
File *File
HorizontalLogoFile *File
Description **string
WebsiteURL **string
Email **string
HeadquarterAddress **string
}
UpdateOrganizationContextRequest struct {
@@ -70,10 +65,6 @@ func (uor *UpdateOrganizationRequest) Validate() error {
v.Check(uor.ID, "id", validator.Required(), validator.GID(coredata.OrganizationEntityType))
v.Check(uor.Name, "name", validator.SafeTextNoNewLine(TitleMaxLength))
v.Check(uor.Description, "description", validator.SafeText(ContentMaxLength))
v.Check(uor.WebsiteURL, "website_url", validator.SafeText(2048))
v.Check(uor.Email, "email", validator.SafeText(255))
v.Check(uor.HeadquarterAddress, "headquarter_address", validator.SafeText(2048))
v.Check(uor.File, "file", validator.NotEmpty())
v.Check(uor.HorizontalLogoFile, "horizontal_logo_file", validator.NotEmpty())
@@ -256,28 +247,6 @@ func (s OrganizationService) Update(
organization.Name = *req.Name
}
if req.Description != nil {
organization.Description = *req.Description
}
if req.WebsiteURL != nil {
organization.WebsiteURL = *req.WebsiteURL
}
if req.Email != nil {
if *req.Email != nil {
if _, err := mail.ParseAddress(**req.Email); err != nil {
return fmt.Errorf("invalid email address: %w", err)
}
}
organization.Email = *req.Email
}
if req.HeadquarterAddress != nil {
organization.HeadquarterAddress = *req.HeadquarterAddress
}
if err := organization.Update(ctx, scope, tx); err != nil {
return fmt.Errorf("cannot update organization: %w", err)
}