summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/ap/interfaces.go14
-rw-r--r--internal/ap/properties.go42
-rw-r--r--internal/db/bundb/account.go36
-rw-r--r--internal/db/bundb/admin.go29
-rw-r--r--internal/db/bundb/migrations/20250708074906_unauthed_web_updates.go164
-rw-r--r--internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common/visibility.go50
-rw-r--r--internal/db/bundb/migrations/20250708074906_unauthed_web_updates/new/account.go102
-rw-r--r--internal/db/bundb/migrations/20250708074906_unauthed_web_updates/old/account.go96
-rw-r--r--internal/filter/visibility/status.go56
-rw-r--r--internal/gtsmodel/account.go10
-rw-r--r--internal/gtsmodel/accountsettings.go1
-rw-r--r--internal/processing/account/update.go46
-rw-r--r--internal/processing/timeline/public_test.go6
-rw-r--r--internal/transport/dereference_test.go7
-rw-r--r--internal/typeutils/astointernal.go4
-rw-r--r--internal/typeutils/internaltoas.go4
-rw-r--r--internal/typeutils/internaltoas_test.go21
-rw-r--r--internal/typeutils/internaltofrontend.go19
-rw-r--r--internal/typeutils/internaltofrontend_test.go4
-rw-r--r--internal/typeutils/wrap_test.go3
20 files changed, 616 insertions, 98 deletions
diff --git a/internal/ap/interfaces.go b/internal/ap/interfaces.go
index faf793bd8..ec961f80b 100644
--- a/internal/ap/interfaces.go
+++ b/internal/ap/interfaces.go
@@ -227,6 +227,8 @@ type Accountable interface {
WithMovedTo
WithAlsoKnownAs
WithManuallyApprovesFollowers
+ WithHidesToPublicFromUnauthedWeb
+ WithHidesCcPublicFromUnauthedWeb
WithEndpoints
WithTag
WithPublished
@@ -711,6 +713,18 @@ type WithManuallyApprovesFollowers interface {
SetActivityStreamsManuallyApprovesFollowers(vocab.ActivityStreamsManuallyApprovesFollowersProperty)
}
+// WithHidesToPublicFromUnauthedWeb represents a Person or profile with the hidesToPublicFromUnauthedWeb property.
+type WithHidesToPublicFromUnauthedWeb interface {
+ GetGoToSocialHidesToPublicFromUnauthedWeb() vocab.GoToSocialHidesToPublicFromUnauthedWebProperty
+ SetGoToSocialHidesToPublicFromUnauthedWeb(vocab.GoToSocialHidesToPublicFromUnauthedWebProperty)
+}
+
+// WithHidesCcPublicFromUnauthedWeb represents a Person or profile with the hidesCcPublicFromUnauthedWeb property.
+type WithHidesCcPublicFromUnauthedWeb interface {
+ GetGoToSocialHidesCcPublicFromUnauthedWeb() vocab.GoToSocialHidesCcPublicFromUnauthedWebProperty
+ SetGoToSocialHidesCcPublicFromUnauthedWeb(vocab.GoToSocialHidesCcPublicFromUnauthedWebProperty)
+}
+
// WithEndpoints represents a Person or profile with the endpoints property
type WithEndpoints interface {
GetActivityStreamsEndpoints() vocab.ActivityStreamsEndpointsProperty
diff --git a/internal/ap/properties.go b/internal/ap/properties.go
index 722c3fca5..3e064bae0 100644
--- a/internal/ap/properties.go
+++ b/internal/ap/properties.go
@@ -562,6 +562,48 @@ func SetManuallyApprovesFollowers(with WithManuallyApprovesFollowers, manuallyAp
mafProp.Set(manuallyApprovesFollowers)
}
+// GetHidesToPublicFromUnauthedWeb returns the boolean contained in the hidesToPublicFromUnauthedWeb property of 'with'.
+//
+// Returns default 'false' if property unusable or not set.
+func GetHidesToPublicFromUnauthedWeb(with WithHidesToPublicFromUnauthedWeb) bool {
+ hidesProp := with.GetGoToSocialHidesToPublicFromUnauthedWeb()
+ if hidesProp == nil || !hidesProp.IsXMLSchemaBoolean() {
+ return false
+ }
+ return hidesProp.Get()
+}
+
+// SetHidesToPublicFromUnauthedWeb sets the given boolean on the hidesToPublicFromUnauthedWeb property of 'with'.
+func SetHidesToPublicFromUnauthedWeb(with WithHidesToPublicFromUnauthedWeb, hidesToPublicFromUnauthedWeb bool) {
+ hidesProp := with.GetGoToSocialHidesToPublicFromUnauthedWeb()
+ if hidesProp == nil {
+ hidesProp = streams.NewGoToSocialHidesToPublicFromUnauthedWebProperty()
+ with.SetGoToSocialHidesToPublicFromUnauthedWeb(hidesProp)
+ }
+ hidesProp.Set(hidesToPublicFromUnauthedWeb)
+}
+
+// GetHidesCcPublicFromUnauthedWeb returns the boolean contained in the hidesCcPublicFromUnauthedWeb property of 'with'.
+//
+// Returns default 'true' if property unusable or not set.
+func GetHidesCcPublicFromUnauthedWeb(with WithHidesCcPublicFromUnauthedWeb) bool {
+ hidesProp := with.GetGoToSocialHidesCcPublicFromUnauthedWeb()
+ if hidesProp == nil || !hidesProp.IsXMLSchemaBoolean() {
+ return true
+ }
+ return hidesProp.Get()
+}
+
+// SetHidesCcPublicFromUnauthedWeb sets the given boolean on the hidesCcPublicFromUnauthedWeb property of 'with'.
+func SetHidesCcPublicFromUnauthedWeb(with WithHidesCcPublicFromUnauthedWeb, hidesCcPublicFromUnauthedWeb bool) {
+ hidesProp := with.GetGoToSocialHidesCcPublicFromUnauthedWeb()
+ if hidesProp == nil {
+ hidesProp = streams.NewGoToSocialHidesCcPublicFromUnauthedWebProperty()
+ with.SetGoToSocialHidesCcPublicFromUnauthedWeb(hidesProp)
+ }
+ hidesProp.Set(hidesCcPublicFromUnauthedWeb)
+}
+
// GetApprovedBy returns the URL contained in
// the ApprovedBy property of 'with', if set.
func GetApprovedBy(with WithApprovedBy) *url.URL {
diff --git a/internal/db/bundb/account.go b/internal/db/bundb/account.go
index 66dc3b307..603740f17 100644
--- a/internal/db/bundb/account.go
+++ b/internal/db/bundb/account.go
@@ -1054,10 +1054,21 @@ func (a *accountDB) GetAccountWebStatuses(
return nil, nil
}
- // Check for an easy case: account exposes no statuses via the web.
- webVisibility := account.Settings.WebVisibility
- if webVisibility == gtsmodel.VisibilityNone {
- return nil, db.ErrNoEntries
+ // Derive visibility of statuses on the web.
+ //
+ // We don't account for situations where someone
+ // hides public statuses but shows unlocked/unlisted,
+ // since that's only an option for remote accts.
+ var (
+ hideAll = *account.HidesToPublicFromUnauthedWeb
+ publicOnly = *account.HidesCcPublicFromUnauthedWeb
+ )
+
+ if hideAll {
+ // Account hides all
+ // statuses from web,
+ // nothing to do.
+ return nil, nil
}
// Ensure reasonable
@@ -1075,27 +1086,18 @@ func (a *accountDB) GetAccountWebStatuses(
Column("status.id").
Where("? = ?", bun.Ident("status.account_id"), account.ID)
- // Select statuses for this account according
- // to their web visibility preference.
- switch webVisibility {
-
- case gtsmodel.VisibilityPublic:
+ // Select statuses according to
+ // account's web visibility prefs.
+ if publicOnly {
// Only Public statuses.
q = q.Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic)
-
- case gtsmodel.VisibilityUnlocked:
+ } else {
// Public or Unlocked.
visis := []gtsmodel.Visibility{
gtsmodel.VisibilityPublic,
gtsmodel.VisibilityUnlocked,
}
q = q.Where("? IN (?)", bun.Ident("status.visibility"), bun.In(visis))
-
- default:
- return nil, gtserror.Newf(
- "unrecognized web visibility for account %s: %s",
- account.ID, webVisibility,
- )
}
// Don't show replies, boosts, or
diff --git a/internal/db/bundb/admin.go b/internal/db/bundb/admin.go
index 0666cf8a8..dcf51c6a5 100644
--- a/internal/db/bundb/admin.go
+++ b/internal/db/bundb/admin.go
@@ -120,20 +120,21 @@ func (a *adminDB) NewSignup(ctx context.Context, newSignup gtsmodel.NewSignup) (
}
account = &gtsmodel.Account{
- ID: accountID,
- Username: newSignup.Username,
- DisplayName: newSignup.Username,
- URI: uris.UserURI,
- URL: uris.UserURL,
- InboxURI: uris.InboxURI,
- OutboxURI: uris.OutboxURI,
- FollowingURI: uris.FollowingURI,
- FollowersURI: uris.FollowersURI,
- FeaturedCollectionURI: uris.FeaturedCollectionURI,
- ActorType: gtsmodel.AccountActorTypePerson,
- PrivateKey: privKey,
- PublicKey: &privKey.PublicKey,
- PublicKeyURI: uris.PublicKeyURI,
+ ID: accountID,
+ Username: newSignup.Username,
+ DisplayName: newSignup.Username,
+ URI: uris.UserURI,
+ URL: uris.UserURL,
+ InboxURI: uris.InboxURI,
+ OutboxURI: uris.OutboxURI,
+ FollowingURI: uris.FollowingURI,
+ FollowersURI: uris.FollowersURI,
+ FeaturedCollectionURI: uris.FeaturedCollectionURI,
+ ActorType: gtsmodel.AccountActorTypePerson,
+ PrivateKey: privKey,
+ PublicKey: &privKey.PublicKey,
+ PublicKeyURI: uris.PublicKeyURI,
+ HidesCcPublicFromUnauthedWeb: util.Ptr(true), // GtS default to hide unlisted.
}
// Insert the new account!
diff --git a/internal/db/bundb/migrations/20250708074906_unauthed_web_updates.go b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates.go
new file mode 100644
index 000000000..f69dbac86
--- /dev/null
+++ b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates.go
@@ -0,0 +1,164 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package migrations
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+
+ "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common"
+ newmodel "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/new"
+ oldmodel "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/old"
+ "code.superseriousbusiness.org/gotosocial/internal/log"
+ "github.com/uptrace/bun"
+)
+
+func init() {
+ up := func(ctx context.Context, db *bun.DB) error {
+ return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
+
+ var account *newmodel.Account
+ accountType := reflect.TypeOf(account)
+
+ // Add new columns to accounts
+ // table if they don't exist already.
+ for _, new := range []struct {
+ dbCol string
+ fieldName string
+ }{
+ {
+ dbCol: "hides_to_public_from_unauthed_web",
+ fieldName: "HidesToPublicFromUnauthedWeb",
+ },
+ {
+ dbCol: "hides_cc_public_from_unauthed_web",
+ fieldName: "HidesCcPublicFromUnauthedWeb",
+ },
+ } {
+ exists, err := doesColumnExist(
+ ctx,
+ tx,
+ "accounts",
+ new.dbCol,
+ )
+ if err != nil {
+ return err
+ }
+
+ if exists {
+ // Column already exists.
+ continue
+ }
+
+ // Column doesn't exist yet, add it.
+ colDef, err := getBunColumnDef(tx, accountType, new.fieldName)
+ if err != nil {
+ return fmt.Errorf("error making column def: %w", err)
+ }
+
+ log.Infof(ctx, "adding accounts.%s column...", new.dbCol)
+ if _, err := tx.
+ NewAddColumn().
+ Model(account).
+ ColumnExpr(colDef).
+ Exec(ctx); err != nil {
+ return fmt.Errorf("error adding column: %w", err)
+ }
+ }
+
+ // For each account settings we have
+ // stored on this instance, set the
+ // new account columns to values
+ // corresponding to the setting.
+ allSettings := []*oldmodel.AccountSettings{}
+ if err := tx.
+ NewSelect().
+ Model(&allSettings).
+ Column("account_id", "web_visibility").
+ Scan(ctx); err != nil {
+ return fmt.Errorf("error selecting settings: %w", err)
+ }
+
+ for _, settings := range allSettings {
+
+ // Derive web visibility.
+ var (
+ hidesToPublicFromUnauthedWeb bool
+ hidesCcPublicFromUnauthedWeb bool
+ )
+
+ switch settings.WebVisibility {
+
+ // Show nothing.
+ case common.VisibilityNone:
+ hidesToPublicFromUnauthedWeb = true
+ hidesCcPublicFromUnauthedWeb = true
+
+ // Show public only (GtS default).
+ case common.VisibilityPublic:
+ hidesToPublicFromUnauthedWeb = false
+ hidesCcPublicFromUnauthedWeb = true
+
+ // Show public + unlisted (Masto default).
+ case common.VisibilityUnlocked:
+ hidesToPublicFromUnauthedWeb = false
+ hidesCcPublicFromUnauthedWeb = false
+
+ default:
+ log.Warnf(ctx,
+ "local account %s had unrecognized settings.WebVisibility %d, skipping...",
+ settings.AccountID, settings.WebVisibility,
+ )
+ continue
+ }
+
+ // Update account.
+ if _, err := tx.
+ NewUpdate().
+ Table("accounts").
+ Set("? = ?", bun.Ident("hides_to_public_from_unauthed_web"), hidesToPublicFromUnauthedWeb).
+ Set("? = ?", bun.Ident("hides_cc_public_from_unauthed_web"), hidesCcPublicFromUnauthedWeb).
+ Where("? = ?", bun.Ident("id"), settings.AccountID).Exec(ctx); err != nil {
+ return fmt.Errorf("error updating local account: %w", err)
+ }
+ }
+
+ // Drop the old web_visibility column.
+ if _, err := tx.
+ NewDropColumn().
+ Model((*oldmodel.AccountSettings)(nil)).
+ Column("web_visibility").
+ Exec(ctx); err != nil {
+ return fmt.Errorf("error dropping old web_visibility column: %w", err)
+ }
+
+ return nil
+ })
+ }
+
+ down := func(ctx context.Context, db *bun.DB) error {
+ return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
+ return nil
+ })
+ }
+
+ if err := Migrations.Register(up, down); err != nil {
+ panic(err)
+ }
+}
diff --git a/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common/visibility.go b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common/visibility.go
new file mode 100644
index 000000000..51cb13d87
--- /dev/null
+++ b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common/visibility.go
@@ -0,0 +1,50 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package common
+
+// Visibility represents the
+// visibility granularity of a status.
+type Visibility int16
+
+const (
+ // VisibilityNone means nobody can see this.
+ // It's only used for web status visibility.
+ VisibilityNone Visibility = 1
+
+ // VisibilityPublic means this status will
+ // be visible to everyone on all timelines.
+ VisibilityPublic Visibility = 2
+
+ // VisibilityUnlocked means this status will be visible to everyone,
+ // but will only show on home timeline to followers, and in lists.
+ VisibilityUnlocked Visibility = 3
+
+ // VisibilityFollowersOnly means this status is viewable to followers only.
+ VisibilityFollowersOnly Visibility = 4
+
+ // VisibilityMutualsOnly means this status
+ // is visible to mutual followers only.
+ VisibilityMutualsOnly Visibility = 5
+
+ // VisibilityDirect means this status is
+ // visible only to mentioned recipients.
+ VisibilityDirect Visibility = 6
+
+ // VisibilityDefault is used when no other setting can be found.
+ VisibilityDefault Visibility = VisibilityUnlocked
+)
diff --git a/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/new/account.go b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/new/account.go
new file mode 100644
index 000000000..ad25a5bc9
--- /dev/null
+++ b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/new/account.go
@@ -0,0 +1,102 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package gtsmodel
+
+import (
+ "crypto/rsa"
+ "time"
+
+ "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common"
+)
+
+type Account struct {
+ ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+ CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ FetchedAt time.Time `bun:"type:timestamptz,nullzero"`
+ Username string `bun:",nullzero,notnull,unique:accounts_username_domain_uniq"`
+ Domain string `bun:",nullzero,unique:accounts_username_domain_uniq"`
+ AvatarMediaAttachmentID string `bun:"type:CHAR(26),nullzero"`
+ AvatarRemoteURL string `bun:",nullzero"`
+ HeaderMediaAttachmentID string `bun:"type:CHAR(26),nullzero"`
+ HeaderRemoteURL string `bun:",nullzero"`
+ DisplayName string `bun:",nullzero"`
+ EmojiIDs []string `bun:"emojis,array"`
+ Fields []*Field `bun:",nullzero"`
+ FieldsRaw []*Field `bun:",nullzero"`
+ Note string `bun:",nullzero"`
+ NoteRaw string `bun:",nullzero"`
+ AlsoKnownAsURIs []string `bun:"also_known_as_uris,array"`
+ AlsoKnownAs []*Account `bun:"-"`
+ MovedToURI string `bun:",nullzero"`
+ MovedTo *Account `bun:"-"`
+ MoveID string `bun:"type:CHAR(26),nullzero"`
+ Locked *bool `bun:",nullzero,notnull,default:true"`
+ Discoverable *bool `bun:",nullzero,notnull,default:false"`
+ URI string `bun:",nullzero,notnull,unique"`
+ URL string `bun:",nullzero"`
+ InboxURI string `bun:",nullzero"`
+ SharedInboxURI *string `bun:""`
+ OutboxURI string `bun:",nullzero"`
+ FollowingURI string `bun:",nullzero"`
+ FollowersURI string `bun:",nullzero"`
+ FeaturedCollectionURI string `bun:",nullzero"`
+ ActorType int16 `bun:",nullzero,notnull"`
+ PrivateKey *rsa.PrivateKey `bun:""`
+ PublicKey *rsa.PublicKey `bun:",notnull"`
+ PublicKeyURI string `bun:",nullzero,notnull,unique"`
+ PublicKeyExpiresAt time.Time `bun:"type:timestamptz,nullzero"`
+ MemorializedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SensitizedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SilencedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SuspendedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SuspensionOrigin string `bun:"type:CHAR(26),nullzero"`
+
+ // Added in this migration:
+ HidesToPublicFromUnauthedWeb *bool `bun:",nullzero,notnull,default:false"`
+ HidesCcPublicFromUnauthedWeb *bool `bun:",nullzero,notnull,default:false"`
+}
+
+type Field struct {
+ Name string
+ Value string
+ VerifiedAt time.Time `bun:",nullzero"`
+}
+
+type AccountSettings struct {
+ AccountID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+ CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ Privacy common.Visibility `bun:",nullzero,default:3"`
+ Sensitive *bool `bun:",nullzero,notnull,default:false"`
+ Language string `bun:",nullzero,notnull,default:'en'"`
+ StatusContentType string `bun:",nullzero"`
+ Theme string `bun:",nullzero"`
+ CustomCSS string `bun:",nullzero"`
+ EnableRSS *bool `bun:",nullzero,notnull,default:false"`
+ HideCollections *bool `bun:",nullzero,notnull,default:false"`
+ WebLayout int16 `bun:",nullzero,notnull,default:1"`
+ InteractionPolicyDirect *struct{} `bun:""`
+ InteractionPolicyMutualsOnly *struct{} `bun:""`
+ InteractionPolicyFollowersOnly *struct{} `bun:""`
+ InteractionPolicyUnlocked *struct{} `bun:""`
+ InteractionPolicyPublic *struct{} `bun:""`
+
+ // Removed in this migration:
+ // WebVisibility common.Visibility `bun:",nullzero,notnull,default:3"`
+}
diff --git a/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/old/account.go b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/old/account.go
new file mode 100644
index 000000000..0086b1464
--- /dev/null
+++ b/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/old/account.go
@@ -0,0 +1,96 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package gtsmodel
+
+import (
+ "crypto/rsa"
+ "time"
+
+ "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250708074906_unauthed_web_updates/common"
+)
+
+type Account struct {
+ ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+ CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ FetchedAt time.Time `bun:"type:timestamptz,nullzero"`
+ Username string `bun:",nullzero,notnull,unique:accounts_username_domain_uniq"`
+ Domain string `bun:",nullzero,unique:accounts_username_domain_uniq"`
+ AvatarMediaAttachmentID string `bun:"type:CHAR(26),nullzero"`
+ AvatarRemoteURL string `bun:",nullzero"`
+ HeaderMediaAttachmentID string `bun:"type:CHAR(26),nullzero"`
+ HeaderRemoteURL string `bun:",nullzero"`
+ DisplayName string `bun:",nullzero"`
+ EmojiIDs []string `bun:"emojis,array"`
+ Fields []*Field `bun:",nullzero"`
+ FieldsRaw []*Field `bun:",nullzero"`
+ Note string `bun:",nullzero"`
+ NoteRaw string `bun:",nullzero"`
+ AlsoKnownAsURIs []string `bun:"also_known_as_uris,array"`
+ AlsoKnownAs []*Account `bun:"-"`
+ MovedToURI string `bun:",nullzero"`
+ MovedTo *Account `bun:"-"`
+ MoveID string `bun:"type:CHAR(26),nullzero"`
+ Locked *bool `bun:",nullzero,notnull,default:true"`
+ Discoverable *bool `bun:",nullzero,notnull,default:false"`
+ URI string `bun:",nullzero,notnull,unique"`
+ URL string `bun:",nullzero"`
+ InboxURI string `bun:",nullzero"`
+ SharedInboxURI *string `bun:""`
+ OutboxURI string `bun:",nullzero"`
+ FollowingURI string `bun:",nullzero"`
+ FollowersURI string `bun:",nullzero"`
+ FeaturedCollectionURI string `bun:",nullzero"`
+ ActorType int16 `bun:",nullzero,notnull"`
+ PrivateKey *rsa.PrivateKey `bun:""`
+ PublicKey *rsa.PublicKey `bun:",notnull"`
+ PublicKeyURI string `bun:",nullzero,notnull,unique"`
+ PublicKeyExpiresAt time.Time `bun:"type:timestamptz,nullzero"`
+ MemorializedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SensitizedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SilencedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SuspendedAt time.Time `bun:"type:timestamptz,nullzero"`
+ SuspensionOrigin string `bun:"type:CHAR(26),nullzero"`
+}
+
+type Field struct {
+ Name string
+ Value string
+ VerifiedAt time.Time `bun:",nullzero"`
+}
+
+type AccountSettings struct {
+ AccountID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+ CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ Privacy common.Visibility `bun:",nullzero,default:3"`
+ Sensitive *bool `bun:",nullzero,notnull,default:false"`
+ Language string `bun:",nullzero,notnull,default:'en'"`
+ StatusContentType string `bun:",nullzero"`
+ Theme string `bun:",nullzero"`
+ CustomCSS string `bun:",nullzero"`
+ EnableRSS *bool `bun:",nullzero,notnull,default:false"`
+ HideCollections *bool `bun:",nullzero,notnull,default:false"`
+ WebVisibility common.Visibility `bun:",nullzero,notnull,default:3"`
+ WebLayout int16 `bun:",nullzero,notnull,default:1"`
+ InteractionPolicyDirect *struct{} `bun:""`
+ InteractionPolicyMutualsOnly *struct{} `bun:""`
+ InteractionPolicyFollowersOnly *struct{} `bun:""`
+ InteractionPolicyUnlocked *struct{} `bun:""`
+ InteractionPolicyPublic *struct{} `bun:""`
+}
diff --git a/internal/filter/visibility/status.go b/internal/filter/visibility/status.go
index 24fa6f2e6..c46fd369c 100644
--- a/internal/filter/visibility/status.go
+++ b/internal/filter/visibility/status.go
@@ -115,9 +115,7 @@ func (f *Filter) isStatusVisible(
if requester == nil {
// Use a different visibility
// heuristic for unauthed requests.
- return f.isStatusVisibleUnauthed(
- ctx, status,
- )
+ return f.isStatusVisibleUnauthed(status), nil
}
/*
@@ -245,57 +243,29 @@ func isPendingStatusVisible(requester *gtsmodel.Account, status *gtsmodel.Status
return false
}
-// isStatusVisibleUnauthed returns whether status is visible without any unauthenticated account.
-func (f *Filter) isStatusVisibleUnauthed(ctx context.Context, status *gtsmodel.Status) (bool, error) {
-
- // For remote accounts, only show
- // Public statuses via the web.
- if status.Account.IsRemote() {
- return status.Visibility == gtsmodel.VisibilityPublic, nil
- }
+// isStatusVisibleUnauthed returns whether status is visible without authentication.
+func (f *Filter) isStatusVisibleUnauthed(status *gtsmodel.Status) bool {
// If status is local only,
- // never show via the web.
+ // never show without auth.
if status.IsLocalOnly() {
- return false, nil
- }
-
- // Check account's settings to see
- // what they expose. Populate these
- // from the DB if necessary.
- if status.Account.Settings == nil {
- var err error
- status.Account.Settings, err = f.state.DB.GetAccountSettings(ctx, status.Account.ID)
- if err != nil {
- return false, gtserror.Newf(
- "error getting settings for account %s: %w",
- status.Account.ID, err,
- )
- }
+ return false
}
- switch webvis := status.Account.Settings.WebVisibility; webvis {
+ switch status.Visibility {
- // public_only: status must be Public.
case gtsmodel.VisibilityPublic:
- return status.Visibility == gtsmodel.VisibilityPublic, nil
+ // Visible if account doesn't hide Public statuses.
+ return !*status.Account.HidesToPublicFromUnauthedWeb
- // unlisted: status must be Public or Unlocked.
case gtsmodel.VisibilityUnlocked:
- visible := status.Visibility == gtsmodel.VisibilityPublic ||
- status.Visibility == gtsmodel.VisibilityUnlocked
- return visible, nil
+ // Visible if account doesn't hide Unlocked statuses.
+ return !*status.Account.HidesCcPublicFromUnauthedWeb
- // none: never show via the web.
- case gtsmodel.VisibilityNone:
- return false, nil
-
- // Huh?
default:
- return false, gtserror.Newf(
- "unrecognized web visibility for account %s: %s",
- status.Account.ID, webvis,
- )
+ // For all other visibilities,
+ // never show without auth.
+ return false
}
}
diff --git a/internal/gtsmodel/account.go b/internal/gtsmodel/account.go
index 664f1f66a..8b2de6b23 100644
--- a/internal/gtsmodel/account.go
+++ b/internal/gtsmodel/account.go
@@ -272,6 +272,16 @@ type Account struct {
//
// Local accounts only.
Stats *AccountStats `bun:"-"`
+
+ // True if the actor hides to-public statusables
+ // from unauthenticated public access via the web.
+ // Default "false" if not set on the actor model.
+ HidesToPublicFromUnauthedWeb *bool `bun:",nullzero,notnull,default:false"`
+
+ // True if the actor hides cc-public statusables
+ // from unauthenticated public access via the web.
+ // Default "true" if not set on the actor model.
+ HidesCcPublicFromUnauthedWeb *bool `bun:",nullzero,notnull,default:true"`
}
// UsernameDomain returns account @username@domain (missing domain if local).
diff --git a/internal/gtsmodel/accountsettings.go b/internal/gtsmodel/accountsettings.go
index 30fb7e5df..9fa05e139 100644
--- a/internal/gtsmodel/accountsettings.go
+++ b/internal/gtsmodel/accountsettings.go
@@ -35,7 +35,6 @@ type AccountSettings struct {
CustomCSS string `bun:",nullzero"` // Custom CSS that should be displayed for this Account's profile and statuses.
EnableRSS *bool `bun:",nullzero,notnull,default:false"` // enable RSS feed subscription for this account's public posts at [URL]/feed
HideCollections *bool `bun:",nullzero,notnull,default:false"` // Hide this account's followers/following collections.
- WebVisibility Visibility `bun:",nullzero,notnull,default:3"` // Visibility level of statuses that visitors can view via the web profile.
WebLayout WebLayout `bun:",nullzero,notnull,default:1"` // Layout to use when showing this profile via the web.
InteractionPolicyDirect *InteractionPolicy `bun:""` // Interaction policy to use for new direct visibility statuses by this account. If null, assume default policy.
InteractionPolicyMutualsOnly *InteractionPolicy `bun:""` // Interaction policy to use for new mutuals only visibility statuses. If null, assume default policy.
diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go
index f0e3b790b..99dd074a5 100644
--- a/internal/processing/account/update.go
+++ b/internal/processing/account/update.go
@@ -212,6 +212,37 @@ func (p *Processor) Update(ctx context.Context, account *gtsmodel.Account, form
}
}
+ if form.WebVisibility != nil {
+ switch apimodel.Visibility(*form.WebVisibility) {
+
+ // Show none.
+ case apimodel.VisibilityNone:
+ account.HidesToPublicFromUnauthedWeb = util.Ptr(true)
+ account.HidesCcPublicFromUnauthedWeb = util.Ptr(true)
+
+ // Show public only (GtS default).
+ case apimodel.VisibilityPublic:
+ account.HidesToPublicFromUnauthedWeb = util.Ptr(false)
+ account.HidesCcPublicFromUnauthedWeb = util.Ptr(true)
+
+ // Show public and unlisted (Masto default).
+ case apimodel.VisibilityUnlisted:
+ account.HidesToPublicFromUnauthedWeb = util.Ptr(false)
+ account.HidesCcPublicFromUnauthedWeb = util.Ptr(false)
+
+ default:
+ const text = "web_visibility must be one of public, unlisted, or none"
+ err := errors.New(text)
+ return nil, gtserror.NewErrorBadRequest(err, text)
+ }
+
+ acctColumns = append(
+ acctColumns,
+ "hides_to_public_from_unauthed_web",
+ "hides_cc_public_from_unauthed_web",
+ )
+ }
+
// Account settings flags.
if form.Source != nil {
@@ -287,21 +318,6 @@ func (p *Processor) Update(ctx context.Context, account *gtsmodel.Account, form
settingsColumns = append(settingsColumns, "hide_collections")
}
- if form.WebVisibility != nil {
- apiVis := apimodel.Visibility(*form.WebVisibility)
- webVisibility := typeutils.APIVisToVis(apiVis)
- if webVisibility != gtsmodel.VisibilityPublic &&
- webVisibility != gtsmodel.VisibilityUnlocked &&
- webVisibility != gtsmodel.VisibilityNone {
- const text = "web_visibility must be one of public, unlocked, or none"
- err := errors.New(text)
- return nil, gtserror.NewErrorBadRequest(err, text)
- }
-
- account.Settings.WebVisibility = webVisibility
- settingsColumns = append(settingsColumns, "web_visibility")
- }
-
if form.WebLayout != nil {
webLayout := gtsmodel.ParseWebLayout(*form.WebLayout)
if webLayout == gtsmodel.WebLayoutUnknown {
diff --git a/internal/processing/timeline/public_test.go b/internal/processing/timeline/public_test.go
index 3320a45da..cf3ade7e5 100644
--- a/internal/processing/timeline/public_test.go
+++ b/internal/processing/timeline/public_test.go
@@ -67,7 +67,7 @@ func (suite *PublicTestSuite) TestPublicTimelineGetNotEmpty() {
ctx = suite.T().Context()
requester = suite.testAccounts["local_account_1"]
// Select 1 *just above* a status we know should
- // not be in the public timeline -- a public
+ // not be in the public timeline -- an unlisted
// reply to one of admin's statuses.
maxID = "01HE7XJ1CG84TBKH5V9XKBVGF6"
sinceID = ""
@@ -91,9 +91,9 @@ func (suite *PublicTestSuite) TestPublicTimelineGetNotEmpty() {
// some other statuses were filtered out.
suite.NoError(errWithCode)
suite.Len(resp.Items, 1)
- suite.Equal(`<http://localhost:8080/api/v1/timelines/public?limit=1&local=false&max_id=01F8MHCP5P2NWYQ416SBA0XSEV>; rel="next", <http://localhost:8080/api/v1/timelines/public?limit=1&local=false&min_id=01HE7XJ1CG84TBKH5V9XKBVGF5>; rel="prev"`, resp.LinkHeader)
+ suite.Equal(`<http://localhost:8080/api/v1/timelines/public?limit=1&local=false&max_id=01F8MHCP5P2NWYQ416SBA0XSEV>; rel="next", <http://localhost:8080/api/v1/timelines/public?limit=1&local=false&min_id=01FF25D5Q0DH7CHD57CTRS6WK0>; rel="prev"`, resp.LinkHeader)
suite.Equal(`http://localhost:8080/api/v1/timelines/public?limit=1&local=false&max_id=01F8MHCP5P2NWYQ416SBA0XSEV`, resp.NextLink)
- suite.Equal(`http://localhost:8080/api/v1/timelines/public?limit=1&local=false&min_id=01HE7XJ1CG84TBKH5V9XKBVGF5`, resp.PrevLink)
+ suite.Equal(`http://localhost:8080/api/v1/timelines/public?limit=1&local=false&min_id=01FF25D5Q0DH7CHD57CTRS6WK0`, resp.PrevLink)
}
// A timeline containing a status hidden due to filtering should return other statuses with no error.
diff --git a/internal/transport/dereference_test.go b/internal/transport/dereference_test.go
index b9611d1e7..836ba2ba5 100644
--- a/internal/transport/dereference_test.go
+++ b/internal/transport/dereference_test.go
@@ -43,8 +43,8 @@ func (suite *DereferenceTestSuite) TestDerefLocalUser() {
defer resp.Body.Close()
suite.Equal(http.StatusOK, resp.StatusCode)
- suite.EqualValues(2007, resp.ContentLength)
- suite.Equal("2007", resp.Header.Get("Content-Length"))
+ suite.EqualValues(2109, resp.ContentLength)
+ suite.Equal("2109", resp.Header.Get("Content-Length"))
suite.Equal(apiutil.AppActivityLDJSON, resp.Header.Get("Content-Type"))
b, err := io.ReadAll(resp.Body)
@@ -59,6 +59,7 @@ func (suite *DereferenceTestSuite) TestDerefLocalUser() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -75,6 +76,8 @@ func (suite *DereferenceTestSuite) TestDerefLocalUser() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",
diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go
index 35f1e7cb7..ede2b3253 100644
--- a/internal/typeutils/astointernal.go
+++ b/internal/typeutils/astointernal.go
@@ -244,6 +244,10 @@ func (c *Converter) ASRepresentationToAccount(
acct.PublicKey = pkey
acct.PublicKeyURI = pkeyURL.String()
+ // Web visibility for statuses.
+ acct.HidesToPublicFromUnauthedWeb = util.Ptr(ap.GetHidesToPublicFromUnauthedWeb(accountable))
+ acct.HidesCcPublicFromUnauthedWeb = util.Ptr(ap.GetHidesCcPublicFromUnauthedWeb(accountable))
+
return &acct, nil
}
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index 3feecaa9b..ce1501e1a 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -399,6 +399,10 @@ func (c *Converter) AccountToAS(
}
}
+ // Web visibility for statuses.
+ ap.SetHidesToPublicFromUnauthedWeb(accountable, *a.HidesToPublicFromUnauthedWeb)
+ ap.SetHidesCcPublicFromUnauthedWeb(accountable, *a.HidesCcPublicFromUnauthedWeb)
+
return accountable, nil
}
diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go
index 5da103582..f3e19bb81 100644
--- a/internal/typeutils/internaltoas_test.go
+++ b/internal/typeutils/internaltoas_test.go
@@ -48,6 +48,7 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -64,6 +65,8 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",
@@ -116,6 +119,7 @@ func (suite *InternalToASTestSuite) TestAccountToASBot() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -132,6 +136,8 @@ func (suite *InternalToASTestSuite) TestAccountToASBot() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",
@@ -178,6 +184,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithFields() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -209,6 +216,8 @@ func (suite *InternalToASTestSuite) TestAccountToASWithFields() {
"featured": "http://localhost:8080/users/1happyturtle/collections/featured",
"followers": "http://localhost:8080/users/1happyturtle/followers",
"following": "http://localhost:8080/users/1happyturtle/following",
+ "hidesCcPublicFromUnauthedWeb": true,
+ "hidesToPublicFromUnauthedWeb": false,
"id": "http://localhost:8080/users/1happyturtle",
"inbox": "http://localhost:8080/users/1happyturtle/inbox",
"manuallyApprovesFollowers": true,
@@ -256,6 +265,7 @@ func (suite *InternalToASTestSuite) TestAccountToASAliasedAndMoved() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -279,6 +289,8 @@ func (suite *InternalToASTestSuite) TestAccountToASAliasedAndMoved() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",
@@ -328,6 +340,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithOneField() {
// Despite only one field being set, attachments should still be a slice/array.
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -354,6 +367,8 @@ func (suite *InternalToASTestSuite) TestAccountToASWithOneField() {
"featured": "http://localhost:8080/users/1happyturtle/collections/featured",
"followers": "http://localhost:8080/users/1happyturtle/followers",
"following": "http://localhost:8080/users/1happyturtle/following",
+ "hidesCcPublicFromUnauthedWeb": true,
+ "hidesToPublicFromUnauthedWeb": false,
"id": "http://localhost:8080/users/1happyturtle",
"inbox": "http://localhost:8080/users/1happyturtle/inbox",
"manuallyApprovesFollowers": true,
@@ -389,6 +404,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithEmoji() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -406,6 +422,8 @@ func (suite *InternalToASTestSuite) TestAccountToASWithEmoji() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",
@@ -464,6 +482,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithSharedInbox() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -483,6 +502,8 @@ func (suite *InternalToASTestSuite) TestAccountToASWithSharedInbox() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index 3b5af6579..aef38ad6e 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -134,9 +134,26 @@ func (c *Converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmode
statusContentType = a.Settings.StatusContentType
}
+ // Derive web visibility for
+ // this local account's statuses.
+ var webVisibility apimodel.Visibility
+ switch {
+ case *a.HidesToPublicFromUnauthedWeb:
+ // Hides all.
+ webVisibility = apimodel.VisibilityNone
+
+ case !*a.HidesCcPublicFromUnauthedWeb:
+ // Shows unlisted + public (Masto default).
+ webVisibility = apimodel.VisibilityUnlisted
+
+ default:
+ // Shows public only (GtS default).
+ webVisibility = apimodel.VisibilityPublic
+ }
+
apiAccount.Source = &apimodel.Source{
Privacy: VisToAPIVis(a.Settings.Privacy),
- WebVisibility: VisToAPIVis(a.Settings.WebVisibility),
+ WebVisibility: webVisibility,
WebLayout: a.Settings.WebLayout.String(),
Sensitive: *a.Settings.Sensitive,
Language: a.Settings.Language,
diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go
index 8b0d15f10..a26ff114e 100644
--- a/internal/typeutils/internaltofrontend_test.go
+++ b/internal/typeutils/internaltofrontend_test.go
@@ -965,7 +965,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendUnknownAttachments
"in_reply_to_account_id": "01F8MH17FWEB39HZJ76B6VXSKF",
"sensitive": true,
"spoiler_text": "some unknown media included",
- "visibility": "public",
+ "visibility": "unlisted",
"language": "en",
"uri": "http://example.org/users/Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5",
"url": "http://example.org/@Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5",
@@ -1114,7 +1114,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToWebStatus() {
"in_reply_to_account_id": "01F8MH17FWEB39HZJ76B6VXSKF",
"sensitive": true,
"spoiler_text": "some unknown media included",
- "visibility": "public",
+ "visibility": "unlisted",
"language": "en",
"uri": "http://example.org/users/Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5",
"url": "http://example.org/@Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5",
diff --git a/internal/typeutils/wrap_test.go b/internal/typeutils/wrap_test.go
index 828e6a683..c0c51b37a 100644
--- a/internal/typeutils/wrap_test.go
+++ b/internal/typeutils/wrap_test.go
@@ -178,6 +178,7 @@ func (suite *WrapTestSuite) TestWrapAccountableInUpdate() {
suite.Equal(`{
"@context": [
+ "https://gotosocial.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
{
@@ -198,6 +199,8 @@ func (suite *WrapTestSuite) TestWrapAccountableInUpdate() {
"featured": "http://localhost:8080/users/the_mighty_zork/collections/featured",
"followers": "http://localhost:8080/users/the_mighty_zork/followers",
"following": "http://localhost:8080/users/the_mighty_zork/following",
+ "hidesCcPublicFromUnauthedWeb": false,
+ "hidesToPublicFromUnauthedWeb": false,
"icon": {
"mediaType": "image/jpeg",
"name": "a green goblin looking nasty",