summaryrefslogtreecommitdiff
path: root/internal/db
diff options
context:
space:
mode:
Diffstat (limited to 'internal/db')
-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
6 files changed, 446 insertions, 31 deletions
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:""`
+}