summaryrefslogtreecommitdiff
path: root/internal/db
diff options
context:
space:
mode:
Diffstat (limited to 'internal/db')
-rw-r--r--internal/db/account.go7
-rw-r--r--internal/db/bundb/account.go67
-rw-r--r--internal/db/bundb/migrations/20240906144432_unauthed_visibility.go.go69
3 files changed, 132 insertions, 11 deletions
diff --git a/internal/db/account.go b/internal/db/account.go
index 45a4ccc09..225c8e1d2 100644
--- a/internal/db/account.go
+++ b/internal/db/account.go
@@ -117,12 +117,11 @@ type Account interface {
// In the case of no statuses, this function will return db.ErrNoEntries.
GetAccountPinnedStatuses(ctx context.Context, accountID string) ([]*gtsmodel.Status, error)
- // GetAccountWebStatuses is similar to GetAccountStatuses, but it's specifically for returning statuses that
- // should be visible via the web view of an account. So, only public, federated statuses that aren't boosts
- // or replies.
+ // GetAccountWebStatuses is similar to GetAccountStatuses, but it's specifically for
+ // returning statuses that should be visible via the web view of a *LOCAL* account.
//
// In the case of no statuses, this function will return db.ErrNoEntries.
- GetAccountWebStatuses(ctx context.Context, accountID string, limit int, maxID string) ([]*gtsmodel.Status, error)
+ GetAccountWebStatuses(ctx context.Context, account *gtsmodel.Account, limit int, maxID string) ([]*gtsmodel.Status, error)
// SetAccountHeaderOrAvatar sets the header or avatar for the given accountID to the given media attachment.
SetAccountHeaderOrAvatar(ctx context.Context, mediaAttachment *gtsmodel.MediaAttachment, accountID string) error
diff --git a/internal/db/bundb/account.go b/internal/db/bundb/account.go
index d8ec26291..1569af9cb 100644
--- a/internal/db/bundb/account.go
+++ b/internal/db/bundb/account.go
@@ -1047,7 +1047,18 @@ func (a *accountDB) GetAccountPinnedStatuses(ctx context.Context, accountID stri
return a.state.DB.GetStatusesByIDs(ctx, statusIDs)
}
-func (a *accountDB) GetAccountWebStatuses(ctx context.Context, accountID string, limit int, maxID string) ([]*gtsmodel.Status, error) {
+func (a *accountDB) GetAccountWebStatuses(
+ ctx context.Context,
+ account *gtsmodel.Account,
+ limit int,
+ maxID string,
+) ([]*gtsmodel.Status, error) {
+ // Check for an easy case: account exposes no statuses via the web.
+ webVisibility := account.Settings.WebVisibility
+ if webVisibility == gtsmodel.VisibilityNone {
+ return nil, db.ErrNoEntries
+ }
+
// Ensure reasonable
if limit < 0 {
limit = 0
@@ -1061,14 +1072,36 @@ func (a *accountDB) GetAccountWebStatuses(ctx context.Context, accountID string,
TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")).
// Select only IDs from table
Column("status.id").
- Where("? = ?", bun.Ident("status.account_id"), accountID).
+ Where("? = ?", bun.Ident("status.account_id"), account.ID).
// Don't show replies or boosts.
Where("? IS NULL", bun.Ident("status.in_reply_to_uri")).
- Where("? IS NULL", bun.Ident("status.boost_of_id")).
+ Where("? IS NULL", bun.Ident("status.boost_of_id"))
+
+ // Select statuses for this account according
+ // to their web visibility preference.
+ switch webVisibility {
+
+ case gtsmodel.VisibilityPublic:
// Only Public statuses.
- Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic).
- // Don't show local-only statuses on the web view.
- Where("? = ?", bun.Ident("status.federated"), true)
+ q = q.Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic)
+
+ case gtsmodel.VisibilityUnlocked:
+ // 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 local-only statuses on the web view.
+ q = q.Where("? = ?", bun.Ident("status.federated"), true)
// return only statuses LOWER (ie., older) than maxID
if maxID == "" {
@@ -1145,10 +1178,30 @@ func (a *accountDB) UpdateAccountSettings(
) error {
return a.state.Caches.DB.AccountSettings.Store(settings, func() error {
settings.UpdatedAt = time.Now()
- if len(columns) > 0 {
+
+ switch {
+
+ case len(columns) != 0:
// If we're updating by column,
// ensure "updated_at" is included.
columns = append(columns, "updated_at")
+
+ // If we're updating web_visibility we should
+ // fall through + invalidate visibility cache.
+ if !slices.Contains(columns, "web_visibility") {
+ break // No need to invalidate.
+ }
+
+ // Fallthrough
+ // to invalidate.
+ fallthrough
+
+ case len(columns) == 0:
+ // Status visibility may be changing for this account.
+ // Clear the visibility cache for unauthed requesters.
+ //
+ // todo: invalidate JUST this account's statuses.
+ defer a.state.Caches.Visibility.Clear()
}
if _, err := a.db.
diff --git a/internal/db/bundb/migrations/20240906144432_unauthed_visibility.go.go b/internal/db/bundb/migrations/20240906144432_unauthed_visibility.go.go
new file mode 100644
index 000000000..473783790
--- /dev/null
+++ b/internal/db/bundb/migrations/20240906144432_unauthed_visibility.go.go
@@ -0,0 +1,69 @@
+// 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"
+
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "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 {
+
+ // If column already exists we don't need to do anything.
+ exists, err := doesColumnExist(ctx, tx,
+ "account_settings", "web_visibility",
+ )
+
+ if err != nil {
+ // Real error.
+ return err
+ } else if exists {
+ // Nothing to do.
+ return nil
+ }
+
+ // Create the new column.
+ if _, err := tx.NewAddColumn().
+ Table("account_settings").
+ ColumnExpr(
+ "? TEXT NOT NULL DEFAULT ?",
+ bun.Ident("web_visibility"),
+ gtsmodel.VisibilityPublic,
+ ).
+ Exec(ctx); err != nil {
+ return 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)
+ }
+}