summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2022-08-15 12:35:05 +0200
committerLibravatar GitHub <noreply@github.com>2022-08-15 11:35:05 +0100
commitac6ed3d939fe9dad81aadbd04541e905c625ca82 (patch)
tree6116baf25675837dc99f69c49b9fec2ff112ce5c /internal
parent[frontend] Sensitive media spoilers (#752) (diff)
downloadgotosocial-ac6ed3d939fe9dad81aadbd04541e905c625ca82.tar.xz
[chore] Update bun / sqlite versions; update gtsmodels (#754)
* upstep bun and sqlite versions * allow specific columns to be updated in the db * only update necessary columns for user * bit tidier * only update necessary fields of media_attachment * only update relevant instance fields * update tests * update only specific account columns * use bool pointers on gtsmodels includes attachment, status, account, user * update columns more selectively * test all default fields on new account insert * updating remaining bools on gtsmodels * initialize pointer fields when extracting AP emoji * copy bools properly * add copyBoolPtr convenience function + test it * initialize false bool ptrs a bit more neatly
Diffstat (limited to 'internal')
-rw-r--r--internal/ap/extract.go4
-rw-r--r--internal/api/client/account/accountverify_test.go4
-rw-r--r--internal/api/client/admin/accountaction.go2
-rw-r--r--internal/api/client/admin/domainblockcreate.go2
-rw-r--r--internal/api/client/admin/domainblockdelete.go2
-rw-r--r--internal/api/client/admin/domainblockget.go2
-rw-r--r--internal/api/client/admin/domainblocksget.go2
-rw-r--r--internal/api/client/admin/emojicreate.go2
-rw-r--r--internal/api/client/admin/emojicreate_test.go4
-rw-r--r--internal/api/client/admin/mediacleanup.go2
-rw-r--r--internal/api/client/admin/mediacleanup_test.go12
-rw-r--r--internal/api/client/auth/authorize.go4
-rw-r--r--internal/api/client/auth/authorize_test.go30
-rw-r--r--internal/api/client/instance/instancepatch.go2
-rw-r--r--internal/api/client/instance/instancepeersget_test.go2
-rw-r--r--internal/api/s2s/user/inboxpost_test.go4
-rw-r--r--internal/api/security/tokencheck.go4
-rw-r--r--internal/cache/account.go12
-rw-r--r--internal/cache/status.go14
-rw-r--r--internal/cache/status_test.go26
-rw-r--r--internal/cache/util.go31
-rw-r--r--internal/db/basic.go6
-rw-r--r--internal/db/bundb/account.go6
-rw-r--r--internal/db/bundb/account_test.go10
-rw-r--r--internal/db/bundb/admin.go10
-rw-r--r--internal/db/bundb/basic.go3
-rw-r--r--internal/db/bundb/basic_test.go70
-rw-r--r--internal/db/bundb/bundb.go8
-rw-r--r--internal/db/bundb/notification_test.go3
-rw-r--r--internal/db/bundb/relationship.go4
-rw-r--r--internal/db/bundb/status_test.go32
-rw-r--r--internal/federation/dereferencing/status_test.go38
-rw-r--r--internal/federation/federatingactor_test.go4
-rw-r--r--internal/federation/federatingdb/owns.go2
-rw-r--r--internal/gtsmodel/account.go12
-rw-r--r--internal/gtsmodel/domainblock.go2
-rw-r--r--internal/gtsmodel/emoji.go4
-rw-r--r--internal/gtsmodel/follow.go4
-rw-r--r--internal/gtsmodel/followrequest.go4
-rw-r--r--internal/gtsmodel/mediaattachment.go6
-rw-r--r--internal/gtsmodel/mention.go2
-rw-r--r--internal/gtsmodel/notification.go2
-rw-r--r--internal/gtsmodel/status.go14
-rw-r--r--internal/gtsmodel/tag.go4
-rw-r--r--internal/gtsmodel/user.go8
-rw-r--r--internal/media/processingemoji.go11
-rw-r--r--internal/media/processingmedia.go18
-rw-r--r--internal/media/prunemeta.go4
-rw-r--r--internal/media/prunemeta_test.go8
-rw-r--r--internal/media/pruneremote.go16
-rw-r--r--internal/media/pruneremote_test.go8
-rw-r--r--internal/media/pruneunusedlocal_test.go4
-rw-r--r--internal/processing/account/createfollow.go12
-rw-r--r--internal/processing/account/delete.go6
-rw-r--r--internal/processing/account/update.go8
-rw-r--r--internal/processing/account/update_test.go4
-rw-r--r--internal/processing/admin/createdomainblock.go17
-rw-r--r--internal/processing/admin/deletedomainblock.go4
-rw-r--r--internal/processing/admin/emoji.go2
-rw-r--r--internal/processing/fromclientapi.go2
-rw-r--r--internal/processing/fromclientapi_test.go13
-rw-r--r--internal/processing/fromfederator.go2
-rw-r--r--internal/processing/fromfederator_test.go72
-rw-r--r--internal/processing/instance.go16
-rw-r--r--internal/processing/media/getfile.go4
-rw-r--r--internal/processing/media/getfile_test.go17
-rw-r--r--internal/processing/media/unattach.go3
-rw-r--r--internal/processing/media/unattach_test.go2
-rw-r--r--internal/processing/media/update.go14
-rw-r--r--internal/processing/status/create.go7
-rw-r--r--internal/processing/status/fave.go2
-rw-r--r--internal/processing/status/util.go10
-rw-r--r--internal/processing/user/changepassword.go5
-rw-r--r--internal/processing/user/emailconfirm.go6
-rw-r--r--internal/processing/user/emailconfirm_test.go6
-rw-r--r--internal/processing/user/user_test.go2
-rw-r--r--internal/trans/model/account.go2
-rw-r--r--internal/trans/model/domainblock.go2
-rw-r--r--internal/trans/model/user.go8
-rw-r--r--internal/typeutils/astointernal.go50
-rw-r--r--internal/typeutils/astointernal_test.go18
-rw-r--r--internal/typeutils/internal.go27
-rw-r--r--internal/typeutils/internaltoas.go6
-rw-r--r--internal/typeutils/internaltofrontend.go16
-rw-r--r--internal/validate/account_test.go13
-rw-r--r--internal/validate/domainblock_test.go3
-rw-r--r--internal/validate/emoji_test.go5
-rw-r--r--internal/validate/mediaattachment_test.go5
-rw-r--r--internal/validate/status_test.go17
-rw-r--r--internal/validate/tag_test.go5
-rw-r--r--internal/validate/user_test.go9
-rw-r--r--internal/visibility/statusboostable.go2
-rw-r--r--internal/visibility/statushometimelineable_test.go72
-rw-r--r--internal/visibility/statusvisible.go4
94 files changed, 635 insertions, 359 deletions
diff --git a/internal/ap/extract.go b/internal/ap/extract.go
index 9417077f3..e1566059c 100644
--- a/internal/ap/extract.go
+++ b/internal/ap/extract.go
@@ -529,6 +529,10 @@ func ExtractEmoji(i Emojiable) (*gtsmodel.Emoji, error) {
}
emoji.ImageRemoteURL = imageURL.String()
+ // assume false for both to begin
+ emoji.Disabled = new(bool)
+ emoji.VisibleInPicker = new(bool)
+
return emoji, nil
}
diff --git a/internal/api/client/account/accountverify_test.go b/internal/api/client/account/accountverify_test.go
index 6b199d83e..886272865 100644
--- a/internal/api/client/account/accountverify_test.go
+++ b/internal/api/client/account/accountverify_test.go
@@ -70,8 +70,8 @@ func (suite *AccountVerifyTestSuite) TestAccountVerifyGet() {
suite.Equal(testAccount.Username, apimodelAccount.Username)
suite.Equal(testAccount.Username, apimodelAccount.Acct)
suite.Equal(testAccount.DisplayName, apimodelAccount.DisplayName)
- suite.Equal(testAccount.Locked, apimodelAccount.Locked)
- suite.Equal(testAccount.Bot, apimodelAccount.Bot)
+ suite.Equal(*testAccount.Locked, apimodelAccount.Locked)
+ suite.Equal(*testAccount.Bot, apimodelAccount.Bot)
suite.WithinDuration(testAccount.CreatedAt, createdAt, 30*time.Second) // we lose a bit of accuracy serializing so fuzz this a bit
suite.Equal(testAccount.URL, apimodelAccount.URL)
suite.Equal("http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpeg", apimodelAccount.Avatar)
diff --git a/internal/api/client/admin/accountaction.go b/internal/api/client/admin/accountaction.go
index 072a60a9d..a9817f295 100644
--- a/internal/api/client/admin/accountaction.go
+++ b/internal/api/client/admin/accountaction.go
@@ -87,7 +87,7 @@ func (m *Module) AccountActionPOSTHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/domainblockcreate.go b/internal/api/client/admin/domainblockcreate.go
index cc97f52ca..9ee725bef 100644
--- a/internal/api/client/admin/domainblockcreate.go
+++ b/internal/api/client/admin/domainblockcreate.go
@@ -123,7 +123,7 @@ func (m *Module) DomainBlocksPOSTHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/domainblockdelete.go b/internal/api/client/admin/domainblockdelete.go
index d57018f72..aec1ba6df 100644
--- a/internal/api/client/admin/domainblockdelete.go
+++ b/internal/api/client/admin/domainblockdelete.go
@@ -75,7 +75,7 @@ func (m *Module) DomainBlockDELETEHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/domainblockget.go b/internal/api/client/admin/domainblockget.go
index e9fdf549b..1aeedce51 100644
--- a/internal/api/client/admin/domainblockget.go
+++ b/internal/api/client/admin/domainblockget.go
@@ -76,7 +76,7 @@ func (m *Module) DomainBlockGETHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/domainblocksget.go b/internal/api/client/admin/domainblocksget.go
index c3b3ec595..93bd767c4 100644
--- a/internal/api/client/admin/domainblocksget.go
+++ b/internal/api/client/admin/domainblocksget.go
@@ -81,7 +81,7 @@ func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/emojicreate.go b/internal/api/client/admin/emojicreate.go
index c5d613312..39ebd5adf 100644
--- a/internal/api/client/admin/emojicreate.go
+++ b/internal/api/client/admin/emojicreate.go
@@ -90,7 +90,7 @@ func (m *Module) EmojiCreatePOSTHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/emojicreate_test.go b/internal/api/client/admin/emojicreate_test.go
index fa93ce564..ebef858aa 100644
--- a/internal/api/client/admin/emojicreate_test.go
+++ b/internal/api/client/admin/emojicreate_test.go
@@ -97,9 +97,9 @@ func (suite *EmojiCreateTestSuite) TestEmojiCreate() {
suite.Equal("image/png", dbEmoji.ImageStaticContentType)
suite.Equal(36702, dbEmoji.ImageFileSize)
suite.Equal(10413, dbEmoji.ImageStaticFileSize)
- suite.False(dbEmoji.Disabled)
+ suite.False(*dbEmoji.Disabled)
suite.NotEmpty(dbEmoji.URI)
- suite.True(dbEmoji.VisibleInPicker)
+ suite.True(*dbEmoji.VisibleInPicker)
suite.Empty(dbEmoji.CategoryID)
// emoji should be in storage
diff --git a/internal/api/client/admin/mediacleanup.go b/internal/api/client/admin/mediacleanup.go
index 6065acd3b..44f0a1b52 100644
--- a/internal/api/client/admin/mediacleanup.go
+++ b/internal/api/client/admin/mediacleanup.go
@@ -74,7 +74,7 @@ func (m *Module) MediaCleanupPOSTHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/admin/mediacleanup_test.go b/internal/api/client/admin/mediacleanup_test.go
index 50f23b2f0..345402ad5 100644
--- a/internal/api/client/admin/mediacleanup_test.go
+++ b/internal/api/client/admin/mediacleanup_test.go
@@ -35,7 +35,7 @@ type MediaCleanupTestSuite struct {
func (suite *MediaCleanupTestSuite) TestMediaCleanup() {
testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_2"]
- suite.True(testAttachment.Cached)
+ suite.True(*testAttachment.Cached)
// set up the request
recorder := httptest.NewRecorder()
@@ -55,12 +55,12 @@ func (suite *MediaCleanupTestSuite) TestMediaCleanup() {
suite.NoError(err)
// the media should no longer be cached
- suite.False(prunedAttachment.Cached)
+ suite.False(*prunedAttachment.Cached)
}
func (suite *MediaCleanupTestSuite) TestMediaCleanupNoArg() {
testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_2"]
- suite.True(testAttachment.Cached)
+ suite.True(*testAttachment.Cached)
println("TIME: ", testAttachment.CreatedAt.String())
// set up the request
@@ -81,12 +81,12 @@ func (suite *MediaCleanupTestSuite) TestMediaCleanupNoArg() {
suite.NoError(err)
// the media should no longer be cached
- suite.False(prunedAttachment.Cached)
+ suite.False(*prunedAttachment.Cached)
}
func (suite *MediaCleanupTestSuite) TestMediaCleanupNotOldEnough() {
testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_2"]
- suite.True(testAttachment.Cached)
+ suite.True(*testAttachment.Cached)
// set up the request
recorder := httptest.NewRecorder()
@@ -106,7 +106,7 @@ func (suite *MediaCleanupTestSuite) TestMediaCleanupNotOldEnough() {
suite.NoError(err)
// the media should still be cached
- suite.True(prunedAttachment.Cached)
+ suite.True(*prunedAttachment.Cached)
}
func TestMediaCleanupTestSuite(t *testing.T) {
diff --git a/internal/api/client/auth/authorize.go b/internal/api/client/auth/authorize.go
index 67325a81d..83cddd9b5 100644
--- a/internal/api/client/auth/authorize.go
+++ b/internal/api/client/auth/authorize.go
@@ -320,13 +320,13 @@ func ensureUserIsAuthorizedOrRedirect(ctx *gin.Context, user *gtsmodel.User, acc
return
}
- if !user.Approved {
+ if !*user.Approved {
ctx.Redirect(http.StatusSeeOther, WaitForApprovalPath)
redirected = true
return
}
- if user.Disabled || !account.SuspendedAt.IsZero() {
+ if *user.Disabled || !account.SuspendedAt.IsZero() {
ctx.Redirect(http.StatusSeeOther, AccountDisabledPath)
redirected = true
return
diff --git a/internal/api/client/auth/authorize_test.go b/internal/api/client/auth/authorize_test.go
index 35b995e70..eab893416 100644
--- a/internal/api/client/auth/authorize_test.go
+++ b/internal/api/client/auth/authorize_test.go
@@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/api/client/auth"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
type AuthAuthorizeTestSuite struct {
@@ -19,7 +20,7 @@ type AuthAuthorizeTestSuite struct {
type authorizeHandlerTestCase struct {
description string
- mutateUserAccount func(*gtsmodel.User, *gtsmodel.Account)
+ mutateUserAccount func(*gtsmodel.User, *gtsmodel.Account) []string
expectedStatusCode int
expectedLocationHeader string
}
@@ -28,40 +29,44 @@ func (suite *AuthAuthorizeTestSuite) TestAccountAuthorizeHandler() {
tests := []authorizeHandlerTestCase{
{
description: "user has their email unconfirmed",
- mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) {
+ mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
// nothing to do, weed_lord420 already has their email unconfirmed
+ return nil
},
expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.CheckYourEmailPath,
},
{
description: "user has their email confirmed but is not approved",
- mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) {
+ mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
user.ConfirmedAt = time.Now()
user.Email = user.UnconfirmedEmail
+ return []string{"confirmed_at", "email"}
},
expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.WaitForApprovalPath,
},
{
description: "user has their email confirmed and is approved, but User entity has been disabled",
- mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) {
+ mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
user.ConfirmedAt = time.Now()
user.Email = user.UnconfirmedEmail
- user.Approved = true
- user.Disabled = true
+ user.Approved = testrig.TrueBool()
+ user.Disabled = testrig.TrueBool()
+ return []string{"confirmed_at", "email", "approved", "disabled"}
},
expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.AccountDisabledPath,
},
{
description: "user has their email confirmed and is approved, but Account entity has been suspended",
- mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) {
+ mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
user.ConfirmedAt = time.Now()
user.Email = user.UnconfirmedEmail
- user.Approved = true
- user.Disabled = false
+ user.Approved = testrig.TrueBool()
+ user.Disabled = testrig.FalseBool()
account.SuspendedAt = time.Now()
+ return []string{"confirmed_at", "email", "approved", "disabled"}
},
expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.AccountDisabledPath,
@@ -81,12 +86,13 @@ func (suite *AuthAuthorizeTestSuite) TestAccountAuthorizeHandler() {
panic(fmt.Errorf("failed on case %s: %w", testCase.description, err))
}
- testCase.mutateUserAccount(user, account)
+ updatingColumns := testCase.mutateUserAccount(user, account)
- testCase.description = fmt.Sprintf("%s, %t, %s", user.Email, user.Disabled, account.SuspendedAt)
+ testCase.description = fmt.Sprintf("%s, %t, %s", user.Email, *user.Disabled, account.SuspendedAt)
+ updatingColumns = append(updatingColumns, "updated_at")
user.UpdatedAt = time.Now()
- err := suite.db.UpdateByPrimaryKey(context.Background(), user)
+ err := suite.db.UpdateByPrimaryKey(context.Background(), user, updatingColumns...)
suite.NoError(err)
_, err = suite.db.UpdateAccount(context.Background(), account)
suite.NoError(err)
diff --git a/internal/api/client/instance/instancepatch.go b/internal/api/client/instance/instancepatch.go
index 6f1b3586b..78d0af046 100644
--- a/internal/api/client/instance/instancepatch.go
+++ b/internal/api/client/instance/instancepatch.go
@@ -124,7 +124,7 @@ func (m *Module) InstanceUpdatePATCHHandler(c *gin.Context) {
return
}
- if !authed.User.Admin {
+ if !*authed.User.Admin {
err := errors.New("user is not an admin so cannot update instance settings")
api.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGet)
return
diff --git a/internal/api/client/instance/instancepeersget_test.go b/internal/api/client/instance/instancepeersget_test.go
index 48fb42a73..cc1adcca4 100644
--- a/internal/api/client/instance/instancepeersget_test.go
+++ b/internal/api/client/instance/instancepeersget_test.go
@@ -190,7 +190,7 @@ func (suite *InstancePeersGetTestSuite) TestInstancePeersGetAllWithObfuscated()
Domain: "omg.just.the.worst.org.ever",
CreatedByAccountID: "01F8MH17FWEB39HZJ76B6VXSKF",
PublicComment: "just absolutely the worst, wowza",
- Obfuscate: true,
+ Obfuscate: testrig.TrueBool(),
})
suite.NoError(err)
diff --git a/internal/api/s2s/user/inboxpost_test.go b/internal/api/s2s/user/inboxpost_test.go
index b8fe73909..506fa270c 100644
--- a/internal/api/s2s/user/inboxpost_test.go
+++ b/internal/api/s2s/user/inboxpost_test.go
@@ -469,8 +469,8 @@ func (suite *InboxPostTestSuite) TestPostDelete() {
suite.Empty(dbAccount.HeaderRemoteURL)
suite.Empty(dbAccount.Reason)
suite.Empty(dbAccount.Fields)
- suite.True(dbAccount.HideCollections)
- suite.False(dbAccount.Discoverable)
+ suite.True(*dbAccount.HideCollections)
+ suite.False(*dbAccount.Discoverable)
suite.WithinDuration(time.Now(), dbAccount.SuspendedAt, 30*time.Second)
suite.Equal(dbAccount.ID, dbAccount.SuspensionOrigin)
}
diff --git a/internal/api/security/tokencheck.go b/internal/api/security/tokencheck.go
index 0e9e7bde2..3df7ee943 100644
--- a/internal/api/security/tokencheck.go
+++ b/internal/api/security/tokencheck.go
@@ -67,12 +67,12 @@ func (m *Module) TokenCheck(c *gin.Context) {
return
}
- if !user.Approved {
+ if !*user.Approved {
log.Warnf("authenticated user %s's account was never approved by an admin", userID)
return
}
- if user.Disabled {
+ if *user.Disabled {
log.Warnf("authenticated user %s's account was disabled'", userID)
return
}
diff --git a/internal/cache/account.go b/internal/cache/account.go
index a71274d1c..ac67b5d07 100644
--- a/internal/cache/account.go
+++ b/internal/cache/account.go
@@ -103,16 +103,16 @@ func copyAccount(account *gtsmodel.Account) *gtsmodel.Account {
Fields: account.Fields,
Note: account.Note,
NoteRaw: account.NoteRaw,
- Memorial: account.Memorial,
+ Memorial: copyBoolPtr(account.Memorial),
MovedToAccountID: account.MovedToAccountID,
+ Bot: copyBoolPtr(account.Bot),
CreatedAt: account.CreatedAt,
UpdatedAt: account.UpdatedAt,
- Bot: account.Bot,
Reason: account.Reason,
- Locked: account.Locked,
- Discoverable: account.Discoverable,
+ Locked: copyBoolPtr(account.Locked),
+ Discoverable: copyBoolPtr(account.Discoverable),
Privacy: account.Privacy,
- Sensitive: account.Sensitive,
+ Sensitive: copyBoolPtr(account.Sensitive),
Language: account.Language,
StatusFormat: account.StatusFormat,
URI: account.URI,
@@ -131,7 +131,7 @@ func copyAccount(account *gtsmodel.Account) *gtsmodel.Account {
SensitizedAt: account.SensitizedAt,
SilencedAt: account.SilencedAt,
SuspendedAt: account.SuspendedAt,
- HideCollections: account.HideCollections,
+ HideCollections: copyBoolPtr(account.HideCollections),
SuspensionOrigin: account.SuspensionOrigin,
}
}
diff --git a/internal/cache/status.go b/internal/cache/status.go
index 7e3d85960..f3cbce779 100644
--- a/internal/cache/status.go
+++ b/internal/cache/status.go
@@ -102,9 +102,9 @@ func copyStatus(status *gtsmodel.Status) *gtsmodel.Status {
Mentions: nil,
EmojiIDs: status.EmojiIDs,
Emojis: nil,
+ Local: copyBoolPtr(status.Local),
CreatedAt: status.CreatedAt,
UpdatedAt: status.UpdatedAt,
- Local: status.Local,
AccountID: status.AccountID,
Account: nil,
AccountURI: status.AccountURI,
@@ -119,15 +119,15 @@ func copyStatus(status *gtsmodel.Status) *gtsmodel.Status {
BoostOfAccount: nil,
ContentWarning: status.ContentWarning,
Visibility: status.Visibility,
- Sensitive: status.Sensitive,
+ Sensitive: copyBoolPtr(status.Sensitive),
Language: status.Language,
CreatedWithApplicationID: status.CreatedWithApplicationID,
- Federated: status.Federated,
- Boostable: status.Boostable,
- Replyable: status.Replyable,
- Likeable: status.Likeable,
ActivityStreamsType: status.ActivityStreamsType,
Text: status.Text,
- Pinned: status.Pinned,
+ Pinned: copyBoolPtr(status.Pinned),
+ Federated: copyBoolPtr(status.Federated),
+ Boostable: copyBoolPtr(status.Boostable),
+ Replyable: copyBoolPtr(status.Replyable),
+ Likeable: copyBoolPtr(status.Likeable),
}
}
diff --git a/internal/cache/status_test.go b/internal/cache/status_test.go
index 882e92be5..8b0621182 100644
--- a/internal/cache/status_test.go
+++ b/internal/cache/status_test.go
@@ -72,6 +72,32 @@ func (suite *StatusCacheTestSuite) TestStatusCache() {
}
}
+func (suite *StatusCacheTestSuite) TestBoolPointerCopying() {
+ originalStatus := suite.data["local_account_1_status_1"]
+
+ // mark the status as pinned + cache it
+ pinned := true
+ originalStatus.Pinned = &pinned
+ suite.cache.Put(originalStatus)
+
+ // retrieve it
+ cachedStatus, ok := suite.cache.GetByID(originalStatus.ID)
+ if !ok {
+ suite.FailNow("status wasn't retrievable from cache")
+ }
+
+ // we should be able to change the original status values + cached
+ // values independently since they use different pointers
+ suite.True(*cachedStatus.Pinned)
+ *originalStatus.Pinned = false
+ suite.False(*originalStatus.Pinned)
+ suite.True(*cachedStatus.Pinned)
+ *originalStatus.Pinned = true
+ *cachedStatus.Pinned = false
+ suite.True(*originalStatus.Pinned)
+ suite.False(*cachedStatus.Pinned)
+}
+
func TestStatusCache(t *testing.T) {
suite.Run(t, &StatusCacheTestSuite{})
}
diff --git a/internal/cache/util.go b/internal/cache/util.go
new file mode 100644
index 000000000..48204b259
--- /dev/null
+++ b/internal/cache/util.go
@@ -0,0 +1,31 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ 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 cache
+
+// copyBoolPtr returns a bool pointer with the same value as the pointer passed into it.
+//
+// Useful when copying things from the cache to a caller.
+func copyBoolPtr(in *bool) *bool {
+ if in == nil {
+ return nil
+ }
+ b := new(bool)
+ *b = *in
+ return b
+}
diff --git a/internal/db/basic.go b/internal/db/basic.go
index 07f04eae3..6e5184d31 100644
--- a/internal/db/basic.go
+++ b/internal/db/basic.go
@@ -62,9 +62,11 @@ type Basic interface {
// The given interface i will be set to the result of the query, whatever it is. Use a pointer or a slice.
Put(ctx context.Context, i interface{}) Error
- // UpdateByPrimaryKey updates all values of i based on its primary key.
+ // UpdateByPrimaryKey updates values of i based on its primary key.
+ // If any columns are specified, these will be updated exclusively.
+ // Otherwise, the whole model will be updated.
// The given interface i will be set to the result of the query, whatever it is. Use a pointer or a slice.
- UpdateByPrimaryKey(ctx context.Context, i interface{}) Error
+ UpdateByPrimaryKey(ctx context.Context, i interface{}, columns ...string) Error
// UpdateWhere updates column key of interface i with the given value, where the given parameters apply.
UpdateWhere(ctx context.Context, where []Where, key string, value interface{}, i interface{}) Error
diff --git a/internal/db/bundb/account.go b/internal/db/bundb/account.go
index aaeb646cf..201de6f02 100644
--- a/internal/db/bundb/account.go
+++ b/internal/db/bundb/account.go
@@ -164,15 +164,15 @@ func (a *accountDB) GetAccountLastPosted(ctx context.Context, accountID string)
}
func (a *accountDB) SetAccountHeaderOrAvatar(ctx context.Context, mediaAttachment *gtsmodel.MediaAttachment, accountID string) db.Error {
- if mediaAttachment.Avatar && mediaAttachment.Header {
+ if *mediaAttachment.Avatar && *mediaAttachment.Header {
return errors.New("one media attachment cannot be both header and avatar")
}
var headerOrAVI string
switch {
- case mediaAttachment.Avatar:
+ case *mediaAttachment.Avatar:
headerOrAVI = "avatar"
- case mediaAttachment.Header:
+ case *mediaAttachment.Header:
headerOrAVI = "header"
default:
return errors.New("given media attachment was neither a header nor an avatar")
diff --git a/internal/db/bundb/account_test.go b/internal/db/bundb/account_test.go
index 134e38940..59b51386d 100644
--- a/internal/db/bundb/account_test.go
+++ b/internal/db/bundb/account_test.go
@@ -93,11 +93,11 @@ func (suite *AccountTestSuite) TestInsertAccountWithDefaults() {
suite.Equal("en", newAccount.Language)
suite.WithinDuration(time.Now(), newAccount.CreatedAt, 30*time.Second)
suite.WithinDuration(time.Now(), newAccount.UpdatedAt, 30*time.Second)
- suite.False(newAccount.Memorial)
- suite.False(newAccount.Bot)
- suite.False(newAccount.Discoverable)
- suite.False(newAccount.Sensitive)
- suite.False(newAccount.HideCollections)
+ suite.False(*newAccount.Memorial)
+ suite.False(*newAccount.Bot)
+ suite.False(*newAccount.Discoverable)
+ suite.False(*newAccount.Sensitive)
+ suite.False(*newAccount.HideCollections)
}
func TestAccountTestSuite(t *testing.T) {
diff --git a/internal/db/bundb/admin.go b/internal/db/bundb/admin.go
index 1bda82d56..f66ed0294 100644
--- a/internal/db/bundb/admin.go
+++ b/internal/db/bundb/admin.go
@@ -142,6 +142,8 @@ func (a *adminDB) NewSignup(ctx context.Context, username string, reason string,
return nil, err
}
+ // if we don't require moderator approval, just pre-approve the user
+ approved := !requireApproval
u := &gtsmodel.User{
ID: newUserID,
AccountID: acct.ID,
@@ -151,7 +153,7 @@ func (a *adminDB) NewSignup(ctx context.Context, username string, reason string,
Locale: locale,
UnconfirmedEmail: email,
CreatedByApplicationID: appID,
- Approved: !requireApproval, // if we don't require moderator approval, just pre-approve the user
+ Approved: &approved,
}
if emailVerified {
@@ -161,8 +163,10 @@ func (a *adminDB) NewSignup(ctx context.Context, username string, reason string,
}
if admin {
- u.Admin = true
- u.Moderator = true
+ admin := true
+ moderator := true
+ u.Admin = &admin
+ u.Moderator = &moderator
}
if _, err = a.conn.
diff --git a/internal/db/bundb/basic.go b/internal/db/bundb/basic.go
index b31a73dd7..cd80c9330 100644
--- a/internal/db/bundb/basic.go
+++ b/internal/db/bundb/basic.go
@@ -94,10 +94,11 @@ func (b *basicDB) DeleteWhere(ctx context.Context, where []db.Where, i interface
return b.conn.ProcessError(err)
}
-func (b *basicDB) UpdateByPrimaryKey(ctx context.Context, i interface{}) db.Error {
+func (b *basicDB) UpdateByPrimaryKey(ctx context.Context, i interface{}, columns ...string) db.Error {
q := b.conn.
NewUpdate().
Model(i).
+ Column(columns...).
WherePK()
_, err := q.Exec(ctx)
diff --git a/internal/db/bundb/basic_test.go b/internal/db/bundb/basic_test.go
index 1705ebc0d..e5ba8b36a 100644
--- a/internal/db/bundb/basic_test.go
+++ b/internal/db/bundb/basic_test.go
@@ -21,6 +21,7 @@ package bundb_test
import (
"context"
"testing"
+ "time"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/db"
@@ -39,6 +40,75 @@ func (suite *BasicTestSuite) TestGetAccountByID() {
suite.NoError(err)
}
+func (suite *BasicTestSuite) TestPutAccountWithBunDefaultFields() {
+ testAccount := &gtsmodel.Account{
+ ID: "01GADR1AH9VCKH8YYCM86XSZ00",
+ Username: "test",
+ URI: "https://example.org/users/test",
+ URL: "https://example.org/@test",
+ InboxURI: "https://example.org/users/test/inbox",
+ OutboxURI: "https://example.org/users/test/outbox",
+ ActorType: "Person",
+ PublicKeyURI: "https://example.org/test#main-key",
+ }
+
+ if err := suite.db.Put(context.Background(), testAccount); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ a := &gtsmodel.Account{}
+ if err := suite.db.GetByID(context.Background(), testAccount.ID, a); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // check all fields are set as expected, including database defaults
+ suite.Equal(testAccount.ID, a.ID)
+ suite.WithinDuration(time.Now(), a.CreatedAt, 5*time.Second)
+ suite.WithinDuration(time.Now(), a.UpdatedAt, 5*time.Second)
+ suite.Equal(testAccount.Username, a.Username)
+ suite.Empty(a.Domain)
+ suite.Empty(a.AvatarMediaAttachmentID)
+ suite.Nil(a.AvatarMediaAttachment)
+ suite.Empty(a.AvatarRemoteURL)
+ suite.Empty(a.HeaderMediaAttachmentID)
+ suite.Nil(a.HeaderMediaAttachment)
+ suite.Empty(a.HeaderRemoteURL)
+ suite.Empty(a.DisplayName)
+ suite.Nil(a.Fields)
+ suite.Empty(a.Note)
+ suite.Empty(a.NoteRaw)
+ suite.False(*a.Memorial)
+ suite.Empty(a.AlsoKnownAs)
+ suite.Empty(a.MovedToAccountID)
+ suite.False(*a.Bot)
+ suite.Empty(a.Reason)
+ // Locked is especially important, since it's a bool that defaults
+ // to true, which is why we use pointers for bools in the first place
+ suite.True(*a.Locked)
+ suite.False(*a.Discoverable)
+ suite.Empty(a.Privacy)
+ suite.False(*a.Sensitive)
+ suite.Equal("en", a.Language)
+ suite.Empty(a.StatusFormat)
+ suite.Equal(testAccount.URI, a.URI)
+ suite.Equal(testAccount.URL, a.URL)
+ suite.Zero(testAccount.LastWebfingeredAt)
+ suite.Equal(testAccount.InboxURI, a.InboxURI)
+ suite.Equal(testAccount.OutboxURI, a.OutboxURI)
+ suite.Empty(a.FollowingURI)
+ suite.Empty(a.FollowersURI)
+ suite.Empty(a.FeaturedCollectionURI)
+ suite.Equal(testAccount.ActorType, a.ActorType)
+ suite.Nil(a.PrivateKey)
+ suite.Nil(a.PublicKey)
+ suite.Equal(testAccount.PublicKeyURI, a.PublicKeyURI)
+ suite.Zero(a.SensitizedAt)
+ suite.Zero(a.SilencedAt)
+ suite.Zero(a.SuspendedAt)
+ suite.False(*a.HideCollections)
+ suite.Empty(a.SuspensionOrigin)
+}
+
func (suite *BasicTestSuite) TestGetAllStatuses() {
s := []*gtsmodel.Status{}
err := suite.db.GetAll(context.Background(), &s)
diff --git a/internal/db/bundb/bundb.go b/internal/db/bundb/bundb.go
index 784a7d443..191350d06 100644
--- a/internal/db/bundb/bundb.go
+++ b/internal/db/bundb/bundb.go
@@ -409,15 +409,17 @@ func (ps *bunDBService) TagStringsToTags(ctx context.Context, tags []string, ori
tag.FirstSeenFromAccountID = originAccountID
tag.CreatedAt = time.Now()
tag.UpdatedAt = time.Now()
- tag.Useable = true
- tag.Listable = true
+ useable := true
+ tag.Useable = &useable
+ listable := true
+ tag.Listable = &listable
} else {
return nil, fmt.Errorf("error getting tag with name %s: %s", t, err)
}
}
// bail already if the tag isn't useable
- if !tag.Useable {
+ if !*tag.Useable {
continue
}
tag.LastStatusAt = time.Now()
diff --git a/internal/db/bundb/notification_test.go b/internal/db/bundb/notification_test.go
index d822c9a28..d79c73ad2 100644
--- a/internal/db/bundb/notification_test.go
+++ b/internal/db/bundb/notification_test.go
@@ -27,6 +27,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/id"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func (suite *NotificationTestSuite) spamNotifs() {
@@ -71,7 +72,7 @@ func (suite *NotificationTestSuite) spamNotifs() {
TargetAccountID: targetAccountID,
OriginAccountID: originAccountID,
StatusID: statusID,
- Read: false,
+ Read: testrig.FalseBool(),
}
if err := suite.db.Put(context.Background(), notif); err != nil {
diff --git a/internal/db/bundb/relationship.go b/internal/db/bundb/relationship.go
index e2e2c96b2..60dd72663 100644
--- a/internal/db/bundb/relationship.go
+++ b/internal/db/bundb/relationship.go
@@ -114,8 +114,8 @@ func (r *relationshipDB) GetRelationship(ctx context.Context, requestingAccount
} else {
// follow exists so we can fill these fields out...
rel.Following = true
- rel.ShowingReblogs = follow.ShowReblogs
- rel.Notifying = follow.Notify
+ rel.ShowingReblogs = *follow.ShowReblogs
+ rel.Notifying = *follow.Notify
}
// check if the target account follows the requesting account
diff --git a/internal/db/bundb/status_test.go b/internal/db/bundb/status_test.go
index 3245314f8..36e329806 100644
--- a/internal/db/bundb/status_test.go
+++ b/internal/db/bundb/status_test.go
@@ -43,10 +43,10 @@ func (suite *StatusTestSuite) TestGetStatusByID() {
suite.Nil(status.BoostOfAccount)
suite.Nil(status.InReplyTo)
suite.Nil(status.InReplyToAccount)
- suite.True(status.Federated)
- suite.True(status.Boostable)
- suite.True(status.Replyable)
- suite.True(status.Likeable)
+ suite.True(*status.Federated)
+ suite.True(*status.Boostable)
+ suite.True(*status.Replyable)
+ suite.True(*status.Likeable)
}
func (suite *StatusTestSuite) TestGetStatusByURI() {
@@ -61,10 +61,10 @@ func (suite *StatusTestSuite) TestGetStatusByURI() {
suite.Nil(status.BoostOfAccount)
suite.Nil(status.InReplyTo)
suite.Nil(status.InReplyToAccount)
- suite.True(status.Federated)
- suite.True(status.Boostable)
- suite.False(status.Replyable)
- suite.False(status.Likeable)
+ suite.True(*status.Federated)
+ suite.True(*status.Boostable)
+ suite.False(*status.Replyable)
+ suite.False(*status.Likeable)
}
func (suite *StatusTestSuite) TestGetStatusWithExtras() {
@@ -78,10 +78,10 @@ func (suite *StatusTestSuite) TestGetStatusWithExtras() {
suite.NotEmpty(status.Tags)
suite.NotEmpty(status.Attachments)
suite.NotEmpty(status.Emojis)
- suite.True(status.Federated)
- suite.True(status.Boostable)
- suite.True(status.Replyable)
- suite.True(status.Likeable)
+ suite.True(*status.Federated)
+ suite.True(*status.Boostable)
+ suite.True(*status.Replyable)
+ suite.True(*status.Likeable)
}
func (suite *StatusTestSuite) TestGetStatusWithMention() {
@@ -95,10 +95,10 @@ func (suite *StatusTestSuite) TestGetStatusWithMention() {
suite.NotEmpty(status.MentionIDs)
suite.NotEmpty(status.InReplyToID)
suite.NotEmpty(status.InReplyToAccountID)
- suite.True(status.Federated)
- suite.True(status.Boostable)
- suite.True(status.Replyable)
- suite.True(status.Likeable)
+ suite.True(*status.Federated)
+ suite.True(*status.Boostable)
+ suite.True(*status.Replyable)
+ suite.True(*status.Likeable)
}
func (suite *StatusTestSuite) TestGetStatusTwice() {
diff --git a/internal/federation/dereferencing/status_test.go b/internal/federation/dereferencing/status_test.go
index 6f6c26145..964de23ec 100644
--- a/internal/federation/dereferencing/status_test.go
+++ b/internal/federation/dereferencing/status_test.go
@@ -46,7 +46,7 @@ func (suite *StatusTestSuite) TestDereferenceSimpleStatus() {
suite.Equal("https://unknown-instance.com/users/@brand_new_person/01FE4NTHKWW7THT67EF10EB839", status.URL)
suite.Equal("Hello world!", status.Content)
suite.Equal("https://unknown-instance.com/users/brand_new_person", status.AccountURI)
- suite.False(status.Local)
+ suite.False(*status.Local)
suite.Empty(status.ContentWarning)
suite.Equal(gtsmodel.VisibilityPublic, status.Visibility)
suite.Equal(ap.ObjectNote, status.ActivityStreamsType)
@@ -55,16 +55,16 @@ func (suite *StatusTestSuite) TestDereferenceSimpleStatus() {
dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI)
suite.NoError(err)
suite.Equal(status.ID, dbStatus.ID)
- suite.True(dbStatus.Federated)
- suite.True(dbStatus.Boostable)
- suite.True(dbStatus.Replyable)
- suite.True(dbStatus.Likeable)
+ suite.True(*dbStatus.Federated)
+ suite.True(*dbStatus.Boostable)
+ suite.True(*dbStatus.Replyable)
+ suite.True(*dbStatus.Likeable)
// account should be in the database now too
account, err := suite.db.GetAccountByURI(context.Background(), status.AccountURI)
suite.NoError(err)
suite.NotNil(account)
- suite.True(account.Discoverable)
+ suite.True(*account.Discoverable)
suite.Equal("https://unknown-instance.com/users/brand_new_person", account.URI)
suite.Equal("hey I'm a new person, your instance hasn't seen me yet uwu", account.Note)
suite.Equal("Geoff Brando New Personson", account.DisplayName)
@@ -86,7 +86,7 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithMention() {
suite.Equal("https://unknown-instance.com/users/@brand_new_person/01FE5Y30E3W4P7TRE0R98KAYQV", status.URL)
suite.Equal("Hey @the_mighty_zork@localhost:8080 how's it going?", status.Content)
suite.Equal("https://unknown-instance.com/users/brand_new_person", status.AccountURI)
- suite.False(status.Local)
+ suite.False(*status.Local)
suite.Empty(status.ContentWarning)
suite.Equal(gtsmodel.VisibilityPublic, status.Visibility)
suite.Equal(ap.ObjectNote, status.ActivityStreamsType)
@@ -95,16 +95,16 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithMention() {
dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI)
suite.NoError(err)
suite.Equal(status.ID, dbStatus.ID)
- suite.True(dbStatus.Federated)
- suite.True(dbStatus.Boostable)
- suite.True(dbStatus.Replyable)
- suite.True(dbStatus.Likeable)
+ suite.True(*dbStatus.Federated)
+ suite.True(*dbStatus.Boostable)
+ suite.True(*dbStatus.Replyable)
+ suite.True(*dbStatus.Likeable)
// account should be in the database now too
account, err := suite.db.GetAccountByURI(context.Background(), status.AccountURI)
suite.NoError(err)
suite.NotNil(account)
- suite.True(account.Discoverable)
+ suite.True(*account.Discoverable)
suite.Equal("https://unknown-instance.com/users/brand_new_person", account.URI)
suite.Equal("hey I'm a new person, your instance hasn't seen me yet uwu", account.Note)
suite.Equal("Geoff Brando New Personson", account.DisplayName)
@@ -121,7 +121,7 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithMention() {
suite.Equal(account.ID, m.OriginAccountID)
suite.Equal(fetchingAccount.ID, m.TargetAccountID)
suite.Equal(account.URI, m.OriginAccountURI)
- suite.False(m.Silent)
+ suite.False(*m.Silent)
}
func (suite *StatusTestSuite) TestDereferenceStatusWithImageAndNoContent() {
@@ -137,7 +137,7 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithImageAndNoContent() {
suite.Equal("https://turnip.farm/@turniplover6969/70c53e54-3146-42d5-a630-83c8b6c7c042", status.URL)
suite.Equal("", status.Content)
suite.Equal("https://turnip.farm/users/turniplover6969", status.AccountURI)
- suite.False(status.Local)
+ suite.False(*status.Local)
suite.Empty(status.ContentWarning)
suite.Equal(gtsmodel.VisibilityPublic, status.Visibility)
suite.Equal(ap.ObjectNote, status.ActivityStreamsType)
@@ -146,16 +146,16 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithImageAndNoContent() {
dbStatus, err := suite.db.GetStatusByURI(context.Background(), status.URI)
suite.NoError(err)
suite.Equal(status.ID, dbStatus.ID)
- suite.True(dbStatus.Federated)
- suite.True(dbStatus.Boostable)
- suite.True(dbStatus.Replyable)
- suite.True(dbStatus.Likeable)
+ suite.True(*dbStatus.Federated)
+ suite.True(*dbStatus.Boostable)
+ suite.True(*dbStatus.Replyable)
+ suite.True(*dbStatus.Likeable)
// account should be in the database now too
account, err := suite.db.GetAccountByURI(context.Background(), status.AccountURI)
suite.NoError(err)
suite.NotNil(account)
- suite.True(account.Discoverable)
+ suite.True(*account.Discoverable)
suite.Equal("https://turnip.farm/users/turniplover6969", account.URI)
suite.Equal("I just think they're neat", account.Note)
suite.Equal("Turnip Lover 6969", account.DisplayName)
diff --git a/internal/federation/federatingactor_test.go b/internal/federation/federatingactor_test.go
index 905b6a7b4..59687345a 100644
--- a/internal/federation/federatingactor_test.go
+++ b/internal/federation/federatingactor_test.go
@@ -82,9 +82,9 @@ func (suite *FederatingActorTestSuite) TestSendRemoteFollower() {
UpdatedAt: testrig.TimeMustParse("2022-06-02T12:22:21+02:00"),
AccountID: testRemoteAccount.ID,
TargetAccountID: testAccount.ID,
- ShowReblogs: true,
+ ShowReblogs: testrig.TrueBool(),
URI: "http://fossbros-anonymous.io/users/foss_satan/follows/01G1TRWV4AYCDBX5HRWT2EVBCV",
- Notify: false,
+ Notify: testrig.FalseBool(),
})
suite.NoError(err)
diff --git a/internal/federation/federatingdb/owns.go b/internal/federation/federatingdb/owns.go
index 51d11f018..6146f9c0a 100644
--- a/internal/federation/federatingdb/owns.go
+++ b/internal/federation/federatingdb/owns.go
@@ -62,7 +62,7 @@ func (f *federatingDB) Owns(ctx context.Context, id *url.URL) (bool, error) {
// an actual error happened
return false, fmt.Errorf("database error fetching status with id %s: %s", uid, err)
}
- return status.Local, nil
+ return *status.Local, nil
}
if uris.IsUserPath(id) {
diff --git a/internal/gtsmodel/account.go b/internal/gtsmodel/account.go
index 9dcb7bd5b..49db7dbda 100644
--- a/internal/gtsmodel/account.go
+++ b/internal/gtsmodel/account.go
@@ -44,15 +44,15 @@ type Account struct {
Fields []Field `validate:"-"` // a key/value map of fields that this account has added to their profile
Note string `validate:"-" bun:""` // A note that this account has on their profile (ie., the account's bio/description of themselves)
NoteRaw string `validate:"-" bun:""` // The raw contents of .Note without conversion to HTML, only available when requester = target
- Memorial bool `validate:"-" bun:",default:false"` // Is this a memorial account, ie., has the user passed away?
+ Memorial *bool `validate:"-" bun:",default:false"` // Is this a memorial account, ie., has the user passed away?
AlsoKnownAs string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"` // This account is associated with x account id (TODO: migrate to be AlsoKnownAsID)
MovedToAccountID string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"` // This account has moved this account id in the database
- Bot bool `validate:"-" bun:",default:false"` // Does this account identify itself as a bot?
+ Bot *bool `validate:"-" bun:",default:false"` // Does this account identify itself as a bot?
Reason string `validate:"-" bun:""` // What reason was given for signing up when this account was created?
- Locked bool `validate:"-" bun:",default:true"` // Does this account need an approval for new followers?
- Discoverable bool `validate:"-" bun:",default:false"` // Should this account be shown in the instance's profile directory?
+ Locked *bool `validate:"-" bun:",default:true"` // Does this account need an approval for new followers?
+ Discoverable *bool `validate:"-" bun:",default:false"` // Should this account be shown in the instance's profile directory?
Privacy Visibility `validate:"required_without=Domain,omitempty,oneof=public unlocked followers_only mutuals_only direct" bun:",nullzero"` // Default post privacy for this account
- Sensitive bool `validate:"-" bun:",default:false"` // Set posts from this account to sensitive by default?
+ Sensitive *bool `validate:"-" bun:",default:false"` // Set posts from this account to sensitive by default?
Language string `validate:"omitempty,bcp47_language_tag" bun:",nullzero,notnull,default:'en'"` // What language does this account post in?
StatusFormat string `validate:"required_without=Domain,omitempty,oneof=plain markdown" bun:",nullzero"` // What is the default format for statuses posted by this account (only for local accounts).
URI string `validate:"required,url" bun:",nullzero,notnull,unique"` // ActivityPub URI for this account.
@@ -70,7 +70,7 @@ type Account struct {
SensitizedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero"` // When was this account set to have all its media shown as sensitive?
SilencedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero"` // When was this account silenced (eg., statuses only visible to followers, not public)?
SuspendedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero"` // When was this account suspended (eg., don't allow it to log in/post, don't accept media/posts from this account)
- HideCollections bool `validate:"-" bun:",default:false"` // Hide this account's collections
+ HideCollections *bool `validate:"-" bun:",default:false"` // Hide this account's collections
SuspensionOrigin string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"` // id of the database entry that caused this account to become suspended -- can be an account ID or a domain block ID
}
diff --git a/internal/gtsmodel/domainblock.go b/internal/gtsmodel/domainblock.go
index 5782b851d..000298aa9 100644
--- a/internal/gtsmodel/domainblock.go
+++ b/internal/gtsmodel/domainblock.go
@@ -30,6 +30,6 @@ type DomainBlock struct {
CreatedByAccount *Account `validate:"-" bun:"rel:belongs-to"` // Account corresponding to createdByAccountID
PrivateComment string `validate:"-" bun:""` // Private comment on this block, viewable to admins
PublicComment string `validate:"-" bun:""` // Public comment on this block, viewable (optionally) by everyone
- Obfuscate bool `validate:"-" bun:",default:false"` // whether the domain name should appear obfuscated when displaying it publicly
+ Obfuscate *bool `validate:"-" bun:",nullzero,notnull,default:false"` // whether the domain name should appear obfuscated when displaying it publicly
SubscriptionID string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"` // if this block was created through a subscription, what's the subscription ID?
}
diff --git a/internal/gtsmodel/emoji.go b/internal/gtsmodel/emoji.go
index 860eb46c8..3460cc63e 100644
--- a/internal/gtsmodel/emoji.go
+++ b/internal/gtsmodel/emoji.go
@@ -38,8 +38,8 @@ type Emoji struct {
ImageFileSize int `validate:"required,min=1" bun:",nullzero,notnull"` // Size of the emoji image file in bytes, for serving purposes.
ImageStaticFileSize int `validate:"required,min=1" bun:",nullzero,notnull"` // Size of the static version of the emoji image file in bytes, for serving purposes.
ImageUpdatedAt time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // When was the emoji image last updated?
- Disabled bool `validate:"-" bun:",notnull,default:false"` // Has a moderation action disabled this emoji from being shown?
+ Disabled *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Has a moderation action disabled this emoji from being shown?
URI string `validate:"url" bun:",nullzero,notnull,unique"` // ActivityPub uri of this emoji. Something like 'https://example.org/emojis/1234'
- VisibleInPicker bool `validate:"-" bun:",notnull,default:true"` // Is this emoji visible in the admin emoji picker?
+ VisibleInPicker *bool `validate:"-" bun:",nullzero,notnull,default:true"` // Is this emoji visible in the admin emoji picker?
CategoryID string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"` // In which emoji category is this emoji visible?
}
diff --git a/internal/gtsmodel/follow.go b/internal/gtsmodel/follow.go
index 15f01cfd2..8f5a01d3b 100644
--- a/internal/gtsmodel/follow.go
+++ b/internal/gtsmodel/follow.go
@@ -30,6 +30,6 @@ type Follow struct {
Account *Account `validate:"-" bun:"rel:belongs-to"` // Account corresponding to accountID
TargetAccountID string `validate:"required,ulid" bun:"type:CHAR(26),unique:srctarget,notnull,nullzero"` // Who is the target of this follow ?
TargetAccount *Account `validate:"-" bun:"rel:belongs-to"` // Account corresponding to targetAccountID
- ShowReblogs bool `validate:"-" bun:",default:true"` // Does this follow also want to see reblogs and not just posts?
- Notify bool `validate:"-" bun:",default:false"` // does the following account want to be notified when the followed account posts?
+ ShowReblogs *bool `validate:"-" bun:",nullzero,notnull,default:true"` // Does this follow also want to see reblogs and not just posts?
+ Notify *bool `validate:"-" bun:",nullzero,notnull,default:false"` // does the following account want to be notified when the followed account posts?
}
diff --git a/internal/gtsmodel/followrequest.go b/internal/gtsmodel/followrequest.go
index 4f7c8b807..b6c49a6ec 100644
--- a/internal/gtsmodel/followrequest.go
+++ b/internal/gtsmodel/followrequest.go
@@ -30,6 +30,6 @@ type FollowRequest struct {
Account *Account `validate:"-" bun:"rel:belongs-to"` // Account corresponding to accountID
TargetAccountID string `validate:"required,ulid" bun:"type:CHAR(26),unique:frsrctarget,notnull,nullzero"` // Who is the target of this follow request?
TargetAccount *Account `validate:"-" bun:"rel:belongs-to"` // Account corresponding to targetAccountID
- ShowReblogs bool `validate:"-" bun:",default:true"` // Does this follow also want to see reblogs and not just posts?
- Notify bool `validate:"-" bun:",default:false"` // does the following account want to be notified when the followed account posts?
+ ShowReblogs *bool `validate:"-" bun:",nullzero,notnull,default:true"` // Does this follow also want to see reblogs and not just posts?
+ Notify *bool `validate:"-" bun:",nullzero,notnull,default:false"` // does the following account want to be notified when the followed account posts?
}
diff --git a/internal/gtsmodel/mediaattachment.go b/internal/gtsmodel/mediaattachment.go
index 2cd287eea..8fe8e2ca6 100644
--- a/internal/gtsmodel/mediaattachment.go
+++ b/internal/gtsmodel/mediaattachment.go
@@ -41,9 +41,9 @@ type MediaAttachment struct {
Processing ProcessingStatus `validate:"oneof=0 1 2 666" bun:",notnull,default:2"` // What is the processing status of this attachment
File File `validate:"required" bun:",embed:file_,notnull,nullzero"` // metadata for the whole file
Thumbnail Thumbnail `validate:"required" bun:",embed:thumbnail_,notnull,nullzero"` // small image thumbnail derived from a larger image, video, or audio file.
- Avatar bool `validate:"-" bun:",notnull,default:false"` // Is this attachment being used as an avatar?
- Header bool `validate:"-" bun:",notnull,default:false"` // Is this attachment being used as a header?
- Cached bool `validate:"-" bun:",notnull"` // Is this attachment currently cached by our instance?
+ Avatar *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Is this attachment being used as an avatar?
+ Header *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Is this attachment being used as a header?
+ Cached *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Is this attachment currently cached by our instance?
}
// File refers to the metadata for the whole file
diff --git a/internal/gtsmodel/mention.go b/internal/gtsmodel/mention.go
index fd1d45622..dfc6cc3f4 100644
--- a/internal/gtsmodel/mention.go
+++ b/internal/gtsmodel/mention.go
@@ -35,7 +35,7 @@ type Mention struct {
OriginAccount *Account `validate:"-" bun:"rel:belongs-to"` // account referred to by originAccountID
TargetAccountID string `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"` // Mention target/receiver account ID
TargetAccount *Account `validate:"-" bun:"rel:belongs-to"` // account referred to by targetAccountID
- Silent bool `validate:"-" bun:",notnull,default:false"` // Prevent this mention from generating a notification?
+ Silent *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Prevent this mention from generating a notification?
/*
NON-DATABASE CONVENIENCE FIELDS
diff --git a/internal/gtsmodel/notification.go b/internal/gtsmodel/notification.go
index 6a5ee06ef..d05898615 100644
--- a/internal/gtsmodel/notification.go
+++ b/internal/gtsmodel/notification.go
@@ -32,7 +32,7 @@ type Notification struct {
OriginAccount *Account `validate:"-" bun:"rel:belongs-to"` // Account corresponding to originAccountID
StatusID string `validate:"required_if=NotificationType mention,required_if=NotificationType reblog,required_if=NotificationType favourite,required_if=NotificationType status,omitempty,ulid" bun:"type:CHAR(26),nullzero"` // If the notification pertains to a status, what is the database ID of that status?
Status *Status `validate:"-" bun:"rel:belongs-to"` // Status corresponding to statusID
- Read bool `validate:"-" bun:",notnull,default:false"` // Notification has been seen/read
+ Read *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Notification has been seen/read
}
// NotificationType describes the reason/type of this notification.
diff --git a/internal/gtsmodel/status.go b/internal/gtsmodel/status.go
index e798ea41b..1b4cc7174 100644
--- a/internal/gtsmodel/status.go
+++ b/internal/gtsmodel/status.go
@@ -38,7 +38,7 @@ type Status struct {
Mentions []*Mention `validate:"-" bun:"attached_mentions,rel:has-many"` // Mentions corresponding to mentionIDs
EmojiIDs []string `validate:"dive,ulid" bun:"emojis,array"` // Database IDs of any emojis used in this status
Emojis []*Emoji `validate:"-" bun:"attached_emojis,m2m:status_to_emojis"` // Emojis corresponding to emojiIDs. https://bun.uptrace.dev/guide/relations.html#many-to-many-relation
- Local bool `validate:"-" bun:",notnull,default:false"` // is this status from a local account?
+ Local *bool `validate:"-" bun:",nullzero,notnull,default:false"` // is this status from a local account?
AccountID string `validate:"required,ulid" bun:"type:CHAR(26),nullzero,notnull"` // which account posted this status?
Account *Account `validate:"-" bun:"rel:belongs-to"` // account corresponding to accountID
AccountURI string `validate:"required,url" bun:",nullzero,notnull"` // activitypub uri of the owner of this status
@@ -53,17 +53,17 @@ type Status struct {
BoostOfAccount *Account `validate:"-" bun:"rel:belongs-to"` // account that corresponds to boostOfAccountID
ContentWarning string `validate:"-" bun:",nullzero"` // cw string for this status
Visibility Visibility `validate:"oneof=public unlocked followers_only mutuals_only direct" bun:",nullzero,notnull"` // visibility entry for this status
- Sensitive bool `validate:"-" bun:",notnull,default:false"` // mark the status as sensitive?
+ Sensitive *bool `validate:"-" bun:",nullzero,notnull,default:false"` // mark the status as sensitive?
Language string `validate:"-" bun:",nullzero"` // what language is this status written in?
CreatedWithApplicationID string `validate:"required_if=Local true,omitempty,ulid" bun:"type:CHAR(26),nullzero"` // Which application was used to create this status?
CreatedWithApplication *Application `validate:"-" bun:"rel:belongs-to"` // application corresponding to createdWithApplicationID
ActivityStreamsType string `validate:"required" bun:",nullzero,notnull"` // What is the activitystreams type of this status? See: https://www.w3.org/TR/activitystreams-vocabulary/#object-types. Will probably almost always be Note but who knows!.
Text string `validate:"-" bun:""` // Original text of the status without formatting
- Pinned bool `validate:"-" bun:",notnull,default:false"` // Has this status been pinned by its owner?
- Federated bool `validate:"-" bun:",notnull"` // This status will be federated beyond the local timeline(s)
- Boostable bool `validate:"-" bun:",notnull"` // This status can be boosted/reblogged
- Replyable bool `validate:"-" bun:",notnull"` // This status can be replied to
- Likeable bool `validate:"-" bun:",notnull"` // This status can be liked/faved
+ Pinned *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Has this status been pinned by its owner?
+ Federated *bool `validate:"-" bun:",notnull"` // This status will be federated beyond the local timeline(s)
+ Boostable *bool `validate:"-" bun:",notnull"` // This status can be boosted/reblogged
+ Replyable *bool `validate:"-" bun:",notnull"` // This status can be replied to
+ Likeable *bool `validate:"-" bun:",notnull"` // This status can be liked/faved
}
/*
diff --git a/internal/gtsmodel/tag.go b/internal/gtsmodel/tag.go
index c73555311..09da27f3a 100644
--- a/internal/gtsmodel/tag.go
+++ b/internal/gtsmodel/tag.go
@@ -28,7 +28,7 @@ type Tag struct {
URL string `validate:"required,url" bun:",nullzero,notnull"` // Href/web address of this tag, eg https://example.org/tags/somehashtag
Name string `validate:"required" bun:",unique,nullzero,notnull"` // name of this tag -- the tag without the hash part
FirstSeenFromAccountID string `validate:"omitempty,ulid" bun:"type:CHAR(26),nullzero"` // Which account ID is the first one we saw using this tag?
- Useable bool `validate:"-" bun:",notnull,default:true"` // can our instance users use this tag?
- Listable bool `validate:"-" bun:",notnull,default:true"` // can our instance users look up this tag?
+ Useable *bool `validate:"-" bun:",nullzero,notnull,default:true"` // can our instance users use this tag?
+ Listable *bool `validate:"-" bun:",nullzero,notnull,default:true"` // can our instance users look up this tag?
LastStatusAt time.Time `validate:"-" bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was this tag last used?
}
diff --git a/internal/gtsmodel/user.go b/internal/gtsmodel/user.go
index 929939572..0d108253a 100644
--- a/internal/gtsmodel/user.go
+++ b/internal/gtsmodel/user.go
@@ -50,10 +50,10 @@ type User struct {
ConfirmationSentAt time.Time `validate:"required_with=ConfirmationToken" bun:"type:timestamptz,nullzero"` // When did we send email confirmation to this user?
ConfirmedAt time.Time `validate:"required_with=Email" bun:"type:timestamptz,nullzero"` // When did the user confirm their email address
UnconfirmedEmail string `validate:"required_without=Email" bun:",nullzero"` // Email address that hasn't yet been confirmed
- Moderator bool `validate:"-" bun:",notnull,default:false"` // Is this user a moderator?
- Admin bool `validate:"-" bun:",notnull,default:false"` // Is this user an admin?
- Disabled bool `validate:"-" bun:",notnull,default:false"` // Is this user disabled from posting?
- Approved bool `validate:"-" bun:",notnull,default:false"` // Has this user been approved by a moderator?
+ Moderator *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Is this user a moderator?
+ Admin *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Is this user an admin?
+ Disabled *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Is this user disabled from posting?
+ Approved *bool `validate:"-" bun:",nullzero,notnull,default:false"` // Has this user been approved by a moderator?
ResetPasswordToken string `validate:"required_with=ResetPasswordSentAt" bun:",nullzero"` // The generated token that the user can use to reset their password
ResetPasswordSentAt time.Time `validate:"required_with=ResetPasswordToken" bun:"type:timestamptz,nullzero"` // When did we email the user their reset-password email?
}
diff --git a/internal/media/processingemoji.go b/internal/media/processingemoji.go
index b28dc7f02..098d0aa19 100644
--- a/internal/media/processingemoji.go
+++ b/internal/media/processingemoji.go
@@ -230,6 +230,9 @@ func (m *manager) preProcessEmoji(ctx context.Context, data DataFunc, postData P
return nil, fmt.Errorf("preProcessEmoji: error fetching this instance account from the db: %s", err)
}
+ disabled := false
+ visibleInPicker := true
+
// populate initial fields on the emoji -- some of these will be overwritten as we proceed
emoji := &gtsmodel.Emoji{
ID: id,
@@ -248,9 +251,9 @@ func (m *manager) preProcessEmoji(ctx context.Context, data DataFunc, postData P
ImageFileSize: 0,
ImageStaticFileSize: 0,
ImageUpdatedAt: time.Now(),
- Disabled: false,
+ Disabled: &disabled,
URI: uri,
- VisibleInPicker: true,
+ VisibleInPicker: &visibleInPicker,
CategoryID: "",
}
@@ -274,11 +277,11 @@ func (m *manager) preProcessEmoji(ctx context.Context, data DataFunc, postData P
}
if ai.Disabled != nil {
- emoji.Disabled = *ai.Disabled
+ emoji.Disabled = ai.Disabled
}
if ai.VisibleInPicker != nil {
- emoji.VisibleInPicker = *ai.VisibleInPicker
+ emoji.VisibleInPicker = ai.VisibleInPicker
}
if ai.CategoryID != nil {
diff --git a/internal/media/processingmedia.go b/internal/media/processingmedia.go
index 885e97417..914d6d276 100644
--- a/internal/media/processingmedia.go
+++ b/internal/media/processingmedia.go
@@ -346,7 +346,9 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
if err := p.storage.PutStream(ctx, p.attachment.File.Path, clean); err != nil {
return fmt.Errorf("store: error storing stream: %s", err)
}
- p.attachment.Cached = true
+
+ cached := true
+ p.attachment.Cached = &cached
p.read = true
if p.postData != nil {
@@ -376,6 +378,10 @@ func (m *manager) preProcessMedia(ctx context.Context, data DataFunc, postData P
UpdatedAt: time.Now(),
}
+ avatar := false
+ header := false
+ cached := false
+
// populate initial fields on the media attachment -- some of these will be overwritten as we proceed
attachment := &gtsmodel.MediaAttachment{
ID: id,
@@ -393,9 +399,9 @@ func (m *manager) preProcessMedia(ctx context.Context, data DataFunc, postData P
Processing: gtsmodel.ProcessingStatusReceived,
File: file,
Thumbnail: thumbnail,
- Avatar: false,
- Header: false,
- Cached: false,
+ Avatar: &avatar,
+ Header: &header,
+ Cached: &cached,
}
// check if we have additional info to add to the attachment,
@@ -426,11 +432,11 @@ func (m *manager) preProcessMedia(ctx context.Context, data DataFunc, postData P
}
if ai.Avatar != nil {
- attachment.Avatar = *ai.Avatar
+ attachment.Avatar = ai.Avatar
}
if ai.Header != nil {
- attachment.Header = *ai.Header
+ attachment.Header = ai.Header
}
if ai.FocusX != nil {
diff --git a/internal/media/prunemeta.go b/internal/media/prunemeta.go
index 7b2b14f98..63bdb00b5 100644
--- a/internal/media/prunemeta.go
+++ b/internal/media/prunemeta.go
@@ -46,8 +46,8 @@ func (m *manager) PruneAllMeta(ctx context.Context) (int, error) {
// - is an avatar but isn't the owning account's current avatar
for _, attachment := range attachments {
if attachment.Account == nil ||
- (attachment.Header && attachment.ID != attachment.Account.HeaderMediaAttachmentID) ||
- (attachment.Avatar && attachment.ID != attachment.Account.AvatarMediaAttachmentID) {
+ (*attachment.Header && attachment.ID != attachment.Account.HeaderMediaAttachmentID) ||
+ (*attachment.Avatar && attachment.ID != attachment.Account.AvatarMediaAttachmentID) {
if err := m.pruneOneAvatarOrHeader(ctx, attachment); err != nil {
return totalPruned, err
}
diff --git a/internal/media/prunemeta_test.go b/internal/media/prunemeta_test.go
index b02156587..32a3b9a5c 100644
--- a/internal/media/prunemeta_test.go
+++ b/internal/media/prunemeta_test.go
@@ -40,7 +40,7 @@ func (suite *PruneMetaTestSuite) TestPruneMeta() {
zork := suite.testAccounts["local_account_1"]
zork.AvatarMediaAttachmentID = ""
zork.HeaderMediaAttachmentID = ""
- if err := suite.db.UpdateByPrimaryKey(ctx, zork); err != nil {
+ if err := suite.db.UpdateByPrimaryKey(ctx, zork, "avatar_media_attachment_id", "header_media_attachment_id"); err != nil {
panic(err)
}
@@ -72,7 +72,7 @@ func (suite *PruneMetaTestSuite) TestPruneMetaTwice() {
zork := suite.testAccounts["local_account_1"]
zork.AvatarMediaAttachmentID = ""
zork.HeaderMediaAttachmentID = ""
- if err := suite.db.UpdateByPrimaryKey(ctx, zork); err != nil {
+ if err := suite.db.UpdateByPrimaryKey(ctx, zork, "avatar_media_attachment_id", "header_media_attachment_id"); err != nil {
panic(err)
}
@@ -95,14 +95,14 @@ func (suite *PruneMetaTestSuite) TestPruneMetaMultipleAccounts() {
zork := suite.testAccounts["local_account_1"]
zork.AvatarMediaAttachmentID = ""
zork.HeaderMediaAttachmentID = ""
- if err := suite.db.UpdateByPrimaryKey(ctx, zork); err != nil {
+ if err := suite.db.UpdateByPrimaryKey(ctx, zork, "avatar_media_attachment_id", "header_media_attachment_id"); err != nil {
panic(err)
}
// set zork's unused header as belonging to turtle
turtle := suite.testAccounts["local_account_1"]
zorkOldHeader.AccountID = turtle.ID
- if err := suite.db.UpdateByPrimaryKey(ctx, zorkOldHeader); err != nil {
+ if err := suite.db.UpdateByPrimaryKey(ctx, zorkOldHeader, "account_id"); err != nil {
panic(err)
}
diff --git a/internal/media/pruneremote.go b/internal/media/pruneremote.go
index 5c3335511..43ce53cdc 100644
--- a/internal/media/pruneremote.go
+++ b/internal/media/pruneremote.go
@@ -64,13 +64,17 @@ func (m *manager) PruneAllRemote(ctx context.Context, olderThanDays int) (int, e
}
func (m *manager) pruneOneRemote(ctx context.Context, attachment *gtsmodel.MediaAttachment) error {
+ var changed bool
+
if attachment.File.Path != "" {
// delete the full size attachment from storage
log.Tracef("pruneOneRemote: deleting %s", attachment.File.Path)
if err := m.storage.Delete(ctx, attachment.File.Path); err != nil && err != storage.ErrNotFound {
return err
}
- attachment.Cached = false
+ cached := false
+ attachment.Cached = &cached
+ changed = true
}
if attachment.Thumbnail.Path != "" {
@@ -79,9 +83,15 @@ func (m *manager) pruneOneRemote(ctx context.Context, attachment *gtsmodel.Media
if err := m.storage.Delete(ctx, attachment.Thumbnail.Path); err != nil && err != storage.ErrNotFound {
return err
}
- attachment.Cached = false
+ cached := false
+ attachment.Cached = &cached
+ changed = true
}
// update the attachment to reflect that we no longer have it cached
- return m.db.UpdateByPrimaryKey(ctx, attachment)
+ if changed {
+ return m.db.UpdateByPrimaryKey(ctx, attachment, "updated_at", "cached")
+ }
+
+ return nil
}
diff --git a/internal/media/pruneremote_test.go b/internal/media/pruneremote_test.go
index f5ed8a618..ddf4cb568 100644
--- a/internal/media/pruneremote_test.go
+++ b/internal/media/pruneremote_test.go
@@ -35,7 +35,7 @@ type PruneRemoteTestSuite struct {
func (suite *PruneRemoteTestSuite) TestPruneRemote() {
testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_1"]
- suite.True(testAttachment.Cached)
+ suite.True(*testAttachment.Cached)
totalPruned, err := suite.manager.PruneAllRemote(context.Background(), 1)
suite.NoError(err)
@@ -45,7 +45,7 @@ func (suite *PruneRemoteTestSuite) TestPruneRemote() {
suite.NoError(err)
// the media should no longer be cached
- suite.False(prunedAttachment.Cached)
+ suite.False(*prunedAttachment.Cached)
}
func (suite *PruneRemoteTestSuite) TestPruneRemoteTwice() {
@@ -91,7 +91,7 @@ func (suite *PruneRemoteTestSuite) TestPruneAndRecache() {
suite.NotNil(recachedAttachment)
// recachedAttachment should be basically the same as the old attachment
- suite.True(recachedAttachment.Cached)
+ suite.True(*recachedAttachment.Cached)
suite.Equal(testAttachment.ID, recachedAttachment.ID)
suite.Equal(testAttachment.File.Path, recachedAttachment.File.Path) // file should be stored in the same place
suite.Equal(testAttachment.Thumbnail.Path, recachedAttachment.Thumbnail.Path) // as should the thumbnail
@@ -111,7 +111,7 @@ func (suite *PruneRemoteTestSuite) TestPruneOneNonExistent() {
// Delete this attachment cached on disk
media, err := suite.db.GetAttachmentByID(ctx, testAttachment.ID)
suite.NoError(err)
- suite.True(media.Cached)
+ suite.True(*media.Cached)
err = suite.storage.Delete(ctx, media.File.Path)
suite.NoError(err)
diff --git a/internal/media/pruneunusedlocal_test.go b/internal/media/pruneunusedlocal_test.go
index 976a6226c..d1424a4c9 100644
--- a/internal/media/pruneunusedlocal_test.go
+++ b/internal/media/pruneunusedlocal_test.go
@@ -32,7 +32,7 @@ type PruneUnusedLocalTestSuite struct {
func (suite *PruneUnusedLocalTestSuite) TestPruneUnusedLocal() {
testAttachment := suite.testAttachments["local_account_1_unattached_1"]
- suite.True(testAttachment.Cached)
+ suite.True(*testAttachment.Cached)
totalPruned, err := suite.manager.PruneUnusedLocalAttachments(context.Background())
suite.NoError(err)
@@ -60,7 +60,7 @@ func (suite *PruneUnusedLocalTestSuite) TestPruneOneNonExistent() {
// Delete this attachment cached on disk
media, err := suite.db.GetAttachmentByID(ctx, testAttachment.ID)
suite.NoError(err)
- suite.True(media.Cached)
+ suite.True(*media.Cached)
err = suite.storage.Delete(ctx, media.File.Path)
suite.NoError(err)
diff --git a/internal/processing/account/createfollow.go b/internal/processing/account/createfollow.go
index 49430b9fb..7e7692135 100644
--- a/internal/processing/account/createfollow.go
+++ b/internal/processing/account/createfollow.go
@@ -76,19 +76,21 @@ func (p *processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode
return nil, gtserror.NewErrorInternalError(err)
}
+ showReblogs := true
+ notify := false
fr := &gtsmodel.FollowRequest{
ID: newFollowID,
AccountID: requestingAccount.ID,
TargetAccountID: form.ID,
- ShowReblogs: true,
+ ShowReblogs: &showReblogs,
URI: uris.GenerateURIForFollow(requestingAccount.Username, newFollowID),
- Notify: false,
+ Notify: &notify,
}
if form.Reblogs != nil {
- fr.ShowReblogs = *form.Reblogs
+ fr.ShowReblogs = form.Reblogs
}
if form.Notify != nil {
- fr.Notify = *form.Notify
+ fr.Notify = form.Notify
}
// whack it in the database
@@ -97,7 +99,7 @@ func (p *processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode
}
// if it's a local account that's not locked we can just straight up accept the follow request
- if !targetAcct.Locked && targetAcct.Domain == "" {
+ if !*targetAcct.Locked && targetAcct.Domain == "" {
if _, err := p.db.AcceptFollowRequest(ctx, requestingAccount.ID, form.ID); err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("accountfollowcreate: error accepting folow request for local unlocked account: %s", err))
}
diff --git a/internal/processing/account/delete.go b/internal/processing/account/delete.go
index 7b382f17c..f71f08954 100644
--- a/internal/processing/account/delete.go
+++ b/internal/processing/account/delete.go
@@ -285,8 +285,10 @@ selectStatusesLoop:
account.HeaderRemoteURL = ""
account.Reason = ""
account.Fields = []gtsmodel.Field{}
- account.HideCollections = true
- account.Discoverable = false
+ hideCollections := true
+ account.HideCollections = &hideCollections
+ discoverable := false
+ account.Discoverable = &discoverable
account.SuspendedAt = time.Now()
account.SuspensionOrigin = origin
diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go
index 804e7ba7e..3b844a160 100644
--- a/internal/processing/account/update.go
+++ b/internal/processing/account/update.go
@@ -39,11 +39,11 @@ import (
func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, gtserror.WithCode) {
if form.Discoverable != nil {
- account.Discoverable = *form.Discoverable
+ account.Discoverable = form.Discoverable
}
if form.Bot != nil {
- account.Bot = *form.Bot
+ account.Bot = form.Bot
}
if form.DisplayName != nil {
@@ -92,7 +92,7 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form
}
if form.Locked != nil {
- account.Locked = *form.Locked
+ account.Locked = form.Locked
}
if form.Source != nil {
@@ -104,7 +104,7 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, form
}
if form.Source.Sensitive != nil {
- account.Sensitive = *form.Source.Sensitive
+ account.Sensitive = form.Source.Sensitive
}
if form.Source.Privacy != nil {
diff --git a/internal/processing/account/update_test.go b/internal/processing/account/update_test.go
index 7e4ca818e..0483154c6 100644
--- a/internal/processing/account/update_test.go
+++ b/internal/processing/account/update_test.go
@@ -65,7 +65,7 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateSimple() {
// fields should be updated in the database as well
dbAccount, err := suite.db.GetAccountByID(context.Background(), testAccount.ID)
suite.NoError(err)
- suite.True(dbAccount.Locked)
+ suite.True(*dbAccount.Locked)
suite.Equal(displayName, dbAccount.DisplayName)
suite.Equal(`<p><a href="http://localhost:8080/tags/hello" class="mention hashtag" rel="tag nofollow noreferrer noopener" target="_blank">#<span>hello</span></a> here i am!</p>`, dbAccount.Note)
}
@@ -107,7 +107,7 @@ func (suite *AccountUpdateTestSuite) TestAccountUpdateWithMention() {
// fields should be updated in the database as well
dbAccount, err := suite.db.GetAccountByID(context.Background(), testAccount.ID)
suite.NoError(err)
- suite.True(dbAccount.Locked)
+ suite.True(*dbAccount.Locked)
suite.Equal(displayName, dbAccount.DisplayName)
suite.Equal(noteExpected, dbAccount.Note)
}
diff --git a/internal/processing/admin/createdomainblock.go b/internal/processing/admin/createdomainblock.go
index b42445380..969cb52de 100644
--- a/internal/processing/admin/createdomainblock.go
+++ b/internal/processing/admin/createdomainblock.go
@@ -62,7 +62,7 @@ func (p *processor) DomainBlockCreate(ctx context.Context, account *gtsmodel.Acc
CreatedByAccountID: account.ID,
PrivateComment: text.SanitizePlaintext(privateComment),
PublicComment: text.SanitizePlaintext(publicComment),
- Obfuscate: obfuscate,
+ Obfuscate: &obfuscate,
SubscriptionID: subscriptionID,
}
@@ -101,6 +101,19 @@ func (p *processor) initiateDomainBlockSideEffects(ctx context.Context, account
// if we have an instance entry for this domain, update it with the new block ID and clear all fields
instance := &gtsmodel.Instance{}
if err := p.db.GetWhere(ctx, []db.Where{{Key: "domain", Value: block.Domain}}, instance); err == nil {
+ updatingColumns := []string{
+ "title",
+ "updated_at",
+ "suspended_at",
+ "domain_block_id",
+ "short_description",
+ "description",
+ "terms",
+ "contact_email",
+ "contact_account_username",
+ "contact_account_id",
+ "version",
+ }
instance.Title = ""
instance.UpdatedAt = time.Now()
instance.SuspendedAt = time.Now()
@@ -112,7 +125,7 @@ func (p *processor) initiateDomainBlockSideEffects(ctx context.Context, account
instance.ContactAccountUsername = ""
instance.ContactAccountID = ""
instance.Version = ""
- if err := p.db.UpdateByPrimaryKey(ctx, instance); err != nil {
+ if err := p.db.UpdateByPrimaryKey(ctx, instance, updatingColumns...); err != nil {
l.Errorf("domainBlockProcessSideEffects: db error updating instance: %s", err)
}
l.Debug("domainBlockProcessSideEffects: instance entry updated")
diff --git a/internal/processing/admin/deletedomainblock.go b/internal/processing/admin/deletedomainblock.go
index 832b9256e..29e911888 100644
--- a/internal/processing/admin/deletedomainblock.go
+++ b/internal/processing/admin/deletedomainblock.go
@@ -58,9 +58,11 @@ func (p *processor) DomainBlockDelete(ctx context.Context, account *gtsmodel.Acc
{Key: "domain", Value: domainBlock.Domain, CaseInsensitive: true},
{Key: "domain_block_id", Value: id},
}, i); err == nil {
+ updatingColumns := []string{"suspended_at", "domain_block_id", "updated_at"}
i.SuspendedAt = time.Time{}
i.DomainBlockID = ""
- if err := p.db.UpdateByPrimaryKey(ctx, i); err != nil {
+ i.UpdatedAt = time.Now()
+ if err := p.db.UpdateByPrimaryKey(ctx, i, updatingColumns...); err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("couldn't update database entry for instance %s: %s", domainBlock.Domain, err))
}
}
diff --git a/internal/processing/admin/emoji.go b/internal/processing/admin/emoji.go
index f91f972a8..36657a6aa 100644
--- a/internal/processing/admin/emoji.go
+++ b/internal/processing/admin/emoji.go
@@ -33,7 +33,7 @@ import (
)
func (p *processor) EmojiCreate(ctx context.Context, account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, gtserror.WithCode) {
- if !user.Admin {
+ if !*user.Admin {
return nil, gtserror.NewErrorUnauthorized(fmt.Errorf("user %s not an admin", user.ID), "user is not an admin")
}
diff --git a/internal/processing/fromclientapi.go b/internal/processing/fromclientapi.go
index 0f684f200..2c4f20d81 100644
--- a/internal/processing/fromclientapi.go
+++ b/internal/processing/fromclientapi.go
@@ -392,7 +392,7 @@ func (p *processor) federateAccountDelete(ctx context.Context, account *gtsmodel
func (p *processor) federateStatus(ctx context.Context, status *gtsmodel.Status) error {
// do nothing if the status shouldn't be federated
- if !status.Federated {
+ if !*status.Federated {
return nil
}
diff --git a/internal/processing/fromclientapi_test.go b/internal/processing/fromclientapi_test.go
index 014266b37..0e620c9e9 100644
--- a/internal/processing/fromclientapi_test.go
+++ b/internal/processing/fromclientapi_test.go
@@ -66,20 +66,21 @@ func (suite *FromClientAPITestSuite) TestProcessStreamNewStatus() {
EmojiIDs: []string{},
CreatedAt: testrig.TimeMustParse("2021-10-20T11:36:45Z"),
UpdatedAt: testrig.TimeMustParse("2021-10-20T11:36:45Z"),
- Local: true,
+ Local: testrig.TrueBool(),
AccountURI: "http://localhost:8080/users/admin",
AccountID: "01F8MH17FWEB39HZJ76B6VXSKF",
InReplyToID: "",
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityFollowersOnly,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "01F8MGXQRHYF5QPMTMXP78QC2F",
- Federated: false, // set federated as false for this one, since we're not testing federation stuff now
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Pinned: testrig.FalseBool(),
+ Federated: testrig.FalseBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
diff --git a/internal/processing/fromfederator.go b/internal/processing/fromfederator.go
index 132b33f4c..ad8273869 100644
--- a/internal/processing/fromfederator.go
+++ b/internal/processing/fromfederator.go
@@ -259,7 +259,7 @@ func (p *processor) processCreateFollowRequestFromFederator(ctx context.Context,
followRequest.TargetAccount = a
}
- if followRequest.TargetAccount.Locked {
+ if *followRequest.TargetAccount.Locked {
// if the account is locked just notify the follow request and nothing else
return p.notifyFollowRequest(ctx, followRequest)
}
diff --git a/internal/processing/fromfederator_test.go b/internal/processing/fromfederator_test.go
index 4d339cb18..86b63dade 100644
--- a/internal/processing/fromfederator_test.go
+++ b/internal/processing/fromfederator_test.go
@@ -84,13 +84,14 @@ func (suite *FromFederatorTestSuite) TestProcessFederationAnnounce() {
suite.Equal(boostedStatus.AccountID, notif.TargetAccountID)
suite.Equal(announceStatus.AccountID, notif.OriginAccountID)
suite.Equal(announceStatus.ID, notif.StatusID)
- suite.False(notif.Read)
+ suite.False(*notif.Read)
}
func (suite *FromFederatorTestSuite) TestProcessReplyMention() {
repliedAccount := suite.testAccounts["local_account_1"]
repliedStatus := suite.testStatuses["local_account_1_status_1"]
replyingAccount := suite.testAccounts["remote_account_1"]
+
replyingStatus := &gtsmodel.Status{
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
@@ -110,10 +111,10 @@ func (suite *FromFederatorTestSuite) TestProcessReplyMention() {
InReplyToAccountID: repliedAccount.ID,
Visibility: gtsmodel.VisibilityUnlocked,
ActivityStreamsType: ap.ObjectNote,
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.FalseBool(),
}
wssStream, errWithCode := suite.processor.OpenStreamForAccount(context.Background(), repliedAccount, stream.TimelineHome)
@@ -156,10 +157,17 @@ func (suite *FromFederatorTestSuite) TestProcessReplyMention() {
suite.Equal(replyingStatus.InReplyToAccountID, notif.TargetAccountID)
suite.Equal(replyingStatus.AccountID, notif.OriginAccountID)
suite.Equal(replyingStatus.ID, notif.StatusID)
- suite.False(notif.Read)
+ suite.False(*notif.Read)
+
+ // the notification should be streamed
+ var msg *stream.Message
+ select {
+ case msg = <-wssStream.Messages:
+ // fine
+ case <-time.After(5 * time.Second):
+ suite.FailNow("no message from wssStream")
+ }
- // the notification should also be streamed
- msg := <-wssStream.Messages
suite.Equal(stream.EventTypeNotification, msg.Event)
suite.NotEmpty(msg.Payload)
suite.EqualValues([]string{stream.TimelineHome}, msg.Stream)
@@ -222,10 +230,16 @@ func (suite *FromFederatorTestSuite) TestProcessFave() {
suite.Equal(fave.TargetAccountID, notif.TargetAccountID)
suite.Equal(fave.AccountID, notif.OriginAccountID)
suite.Equal(fave.StatusID, notif.StatusID)
- suite.False(notif.Read)
+ suite.False(*notif.Read)
// 2. a notification should be streamed
- msg := <-wssStream.Messages
+ var msg *stream.Message
+ select {
+ case msg = <-wssStream.Messages:
+ // fine
+ case <-time.After(5 * time.Second):
+ suite.FailNow("no message from wssStream")
+ }
suite.Equal(stream.EventTypeNotification, msg.Event)
suite.NotEmpty(msg.Payload)
suite.EqualValues([]string{stream.TimelineNotifications}, msg.Stream)
@@ -289,7 +303,7 @@ func (suite *FromFederatorTestSuite) TestProcessFaveWithDifferentReceivingAccoun
suite.Equal(fave.TargetAccountID, notif.TargetAccountID)
suite.Equal(fave.AccountID, notif.OriginAccountID)
suite.Equal(fave.StatusID, notif.StatusID)
- suite.False(notif.Read)
+ suite.False(*notif.Read)
// 2. no notification should be streamed to the account that received the fave message, because they weren't the target
suite.Empty(wssStream.Messages)
@@ -309,9 +323,9 @@ func (suite *FromFederatorTestSuite) TestProcessAccountDelete() {
UpdatedAt: time.Now().Add(-1 * time.Hour),
AccountID: deletedAccount.ID,
TargetAccountID: receivingAccount.ID,
- ShowReblogs: true,
+ ShowReblogs: testrig.TrueBool(),
URI: fmt.Sprintf("%s/follows/01FGRY72ASHBSET64353DPHK9T", deletedAccount.URI),
- Notify: false,
+ Notify: testrig.FalseBool(),
}
err := suite.db.Put(ctx, zorkFollowSatan)
suite.NoError(err)
@@ -322,9 +336,9 @@ func (suite *FromFederatorTestSuite) TestProcessAccountDelete() {
UpdatedAt: time.Now().Add(-1 * time.Hour),
AccountID: receivingAccount.ID,
TargetAccountID: deletedAccount.ID,
- ShowReblogs: true,
+ ShowReblogs: testrig.TrueBool(),
URI: fmt.Sprintf("%s/follows/01FGRYAVAWWPP926J175QGM0WV", receivingAccount.URI),
- Notify: false,
+ Notify: testrig.FalseBool(),
}
err = suite.db.Put(ctx, satanFollowZork)
suite.NoError(err)
@@ -369,8 +383,8 @@ func (suite *FromFederatorTestSuite) TestProcessAccountDelete() {
suite.Empty(dbAccount.HeaderRemoteURL)
suite.Empty(dbAccount.Reason)
suite.Empty(dbAccount.Fields)
- suite.True(dbAccount.HideCollections)
- suite.False(dbAccount.Discoverable)
+ suite.True(*dbAccount.HideCollections)
+ suite.False(*dbAccount.Discoverable)
suite.WithinDuration(time.Now(), dbAccount.SuspendedAt, 30*time.Second)
suite.Equal(dbAccount.ID, dbAccount.SuspensionOrigin)
}
@@ -395,9 +409,9 @@ func (suite *FromFederatorTestSuite) TestProcessFollowRequestLocked() {
Account: originAccount,
TargetAccountID: targetAccount.ID,
TargetAccount: targetAccount,
- ShowReblogs: true,
+ ShowReblogs: testrig.TrueBool(),
URI: fmt.Sprintf("%s/follows/01FGRYAVAWWPP926J175QGM0WV", originAccount.URI),
- Notify: false,
+ Notify: testrig.FalseBool(),
}
err := suite.db.Put(ctx, satanFollowRequestTurtle)
@@ -412,7 +426,13 @@ func (suite *FromFederatorTestSuite) TestProcessFollowRequestLocked() {
suite.NoError(err)
// a notification should be streamed
- msg := <-wssStream.Messages
+ var msg *stream.Message
+ select {
+ case msg = <-wssStream.Messages:
+ // fine
+ case <-time.After(5 * time.Second):
+ suite.FailNow("no message from wssStream")
+ }
suite.Equal(stream.EventTypeNotification, msg.Event)
suite.NotEmpty(msg.Payload)
suite.EqualValues([]string{stream.TimelineHome}, msg.Stream)
@@ -446,9 +466,9 @@ func (suite *FromFederatorTestSuite) TestProcessFollowRequestUnlocked() {
Account: originAccount,
TargetAccountID: targetAccount.ID,
TargetAccount: targetAccount,
- ShowReblogs: true,
+ ShowReblogs: testrig.TrueBool(),
URI: fmt.Sprintf("%s/follows/01FGRYAVAWWPP926J175QGM0WV", originAccount.URI),
- Notify: false,
+ Notify: testrig.FalseBool(),
}
err := suite.db.Put(ctx, satanFollowRequestTurtle)
@@ -463,7 +483,13 @@ func (suite *FromFederatorTestSuite) TestProcessFollowRequestUnlocked() {
suite.NoError(err)
// a notification should be streamed
- msg := <-wssStream.Messages
+ var msg *stream.Message
+ select {
+ case msg = <-wssStream.Messages:
+ // fine
+ case <-time.After(5 * time.Second):
+ suite.FailNow("no message from wssStream")
+ }
suite.Equal(stream.EventTypeNotification, msg.Event)
suite.NotEmpty(msg.Payload)
suite.EqualValues([]string{stream.TimelineHome}, msg.Stream)
diff --git a/internal/processing/instance.go b/internal/processing/instance.go
index 4d1e8b8fd..0a13917ea 100644
--- a/internal/processing/instance.go
+++ b/internal/processing/instance.go
@@ -81,7 +81,7 @@ func (p *processor) InstancePeersGet(ctx context.Context, authed *oauth.Auth, in
}
for _, d := range domainBlocks {
- if d.Obfuscate {
+ if *d.Obfuscate {
d.Domain = obfuscate(d.Domain)
}
@@ -123,11 +123,14 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error fetching instance account %s: %s", host, err))
}
+ updatingColumns := []string{}
+
// validate & update site title if it's set on the form
if form.Title != nil {
if err := validate.SiteTitle(*form.Title); err != nil {
return nil, gtserror.NewErrorBadRequest(err, fmt.Sprintf("site title invalid: %s", err))
}
+ updatingColumns = append(updatingColumns, "title")
i.Title = text.SanitizePlaintext(*form.Title) // don't allow html in site title
}
@@ -153,15 +156,16 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
err := fmt.Errorf("user of selected contact account %s is not confirmed", contactAccount.Username)
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
- if !contactUser.Approved {
+ if !*contactUser.Approved {
err := fmt.Errorf("user of selected contact account %s is not approved", contactAccount.Username)
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
// contact account user must be admin or moderator otherwise what's the point of contacting them
- if !contactUser.Admin && !contactUser.Moderator {
+ if !*contactUser.Admin && !*contactUser.Moderator {
err := fmt.Errorf("user of selected contact account %s is neither admin nor moderator", contactAccount.Username)
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
+ updatingColumns = append(updatingColumns, "contact_account_id")
i.ContactAccountID = contactAccount.ID
}
@@ -173,6 +177,7 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
}
+ updatingColumns = append(updatingColumns, "contact_email")
i.ContactEmail = contactEmail
}
@@ -181,6 +186,7 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
if err := validate.SiteShortDescription(*form.ShortDescription); err != nil {
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
+ updatingColumns = append(updatingColumns, "short_description")
i.ShortDescription = text.SanitizeHTML(*form.ShortDescription) // html is OK in site description, but we should sanitize it
}
@@ -189,6 +195,7 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
if err := validate.SiteDescription(*form.Description); err != nil {
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
+ updatingColumns = append(updatingColumns, "description")
i.Description = text.SanitizeHTML(*form.Description) // html is OK in site description, but we should sanitize it
}
@@ -197,6 +204,7 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
if err := validate.SiteTerms(*form.Terms); err != nil {
return nil, gtserror.NewErrorBadRequest(err, err.Error())
}
+ updatingColumns = append(updatingColumns, "terms")
i.Terms = text.SanitizeHTML(*form.Terms) // html is OK in site terms, but we should sanitize it
}
@@ -216,7 +224,7 @@ func (p *processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe
}
}
- if err := p.db.UpdateByPrimaryKey(ctx, i); err != nil {
+ if err := p.db.UpdateByPrimaryKey(ctx, i, updatingColumns...); err != nil {
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error updating instance %s: %s", host, err))
}
diff --git a/internal/processing/media/getfile.go b/internal/processing/media/getfile.go
index 3227cb8c8..52cdcc052 100644
--- a/internal/processing/media/getfile.go
+++ b/internal/processing/media/getfile.go
@@ -112,7 +112,7 @@ func (p *processor) getAttachmentContent(ctx context.Context, requestingAccount
}
// if we have the media cached on our server already, we can now simply return it from storage
- if a.Cached {
+ if *a.Cached {
return p.retrieveFromStorage(ctx, storagePath, attachmentContent)
}
@@ -236,7 +236,7 @@ func (p *processor) getEmojiContent(ctx context.Context, wantedEmojiID string, e
return nil, gtserror.NewErrorNotFound(fmt.Errorf("emoji %s could not be taken from the db: %s", wantedEmojiID, err))
}
- if e.Disabled {
+ if *e.Disabled {
return nil, gtserror.NewErrorNotFound(fmt.Errorf("emoji %s has been disabled", wantedEmojiID))
}
diff --git a/internal/processing/media/getfile_test.go b/internal/processing/media/getfile_test.go
index 7c6525abe..6ba06426f 100644
--- a/internal/processing/media/getfile_test.go
+++ b/internal/processing/media/getfile_test.go
@@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/suite"
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/media"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
type GetFileTestSuite struct {
@@ -67,8 +68,8 @@ func (suite *GetFileTestSuite) TestGetRemoteFileUncached() {
// uncache the file from local
testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_1"]
- testAttachment.Cached = false
- err := suite.db.UpdateByPrimaryKey(ctx, testAttachment)
+ testAttachment.Cached = testrig.FalseBool()
+ err := suite.db.UpdateByPrimaryKey(ctx, testAttachment, "cached")
suite.NoError(err)
err = suite.storage.Delete(ctx, testAttachment.File.Path)
suite.NoError(err)
@@ -103,7 +104,7 @@ func (suite *GetFileTestSuite) TestGetRemoteFileUncached() {
// the attachment should be updated in the database
dbAttachment, err := suite.db.GetAttachmentByID(ctx, testAttachment.ID)
suite.NoError(err)
- suite.True(dbAttachment.Cached)
+ suite.True(*dbAttachment.Cached)
// the file should be back in storage at the same path as before
refreshedBytes, err := suite.storage.Get(ctx, testAttachment.File.Path)
@@ -116,8 +117,8 @@ func (suite *GetFileTestSuite) TestGetRemoteFileUncachedInterrupted() {
// uncache the file from local
testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_1"]
- testAttachment.Cached = false
- err := suite.db.UpdateByPrimaryKey(ctx, testAttachment)
+ testAttachment.Cached = testrig.FalseBool()
+ err := suite.db.UpdateByPrimaryKey(ctx, testAttachment, "cached")
suite.NoError(err)
err = suite.storage.Delete(ctx, testAttachment.File.Path)
suite.NoError(err)
@@ -153,7 +154,7 @@ func (suite *GetFileTestSuite) TestGetRemoteFileUncachedInterrupted() {
// the attachment should still be updated in the database even though the caller hung up
dbAttachment, err := suite.db.GetAttachmentByID(ctx, testAttachment.ID)
suite.NoError(err)
- suite.True(dbAttachment.Cached)
+ suite.True(*dbAttachment.Cached)
// the file should be back in storage at the same path as before
refreshedBytes, err := suite.storage.Get(ctx, testAttachment.File.Path)
@@ -170,8 +171,8 @@ func (suite *GetFileTestSuite) TestGetRemoteFileThumbnailUncached() {
suite.NoError(err)
// uncache the file from local
- testAttachment.Cached = false
- err = suite.db.UpdateByPrimaryKey(ctx, testAttachment)
+ testAttachment.Cached = testrig.FalseBool()
+ err = suite.db.UpdateByPrimaryKey(ctx, testAttachment, "cached")
suite.NoError(err)
err = suite.storage.Delete(ctx, testAttachment.File.Path)
suite.NoError(err)
diff --git a/internal/processing/media/unattach.go b/internal/processing/media/unattach.go
index bb09525fe..5ef8f81f4 100644
--- a/internal/processing/media/unattach.go
+++ b/internal/processing/media/unattach.go
@@ -43,10 +43,11 @@ func (p *processor) Unattach(ctx context.Context, account *gtsmodel.Account, med
return nil, gtserror.NewErrorNotFound(errors.New("attachment not owned by requesting account"))
}
+ updatingColumns := []string{"updated_at", "status_id"}
attachment.UpdatedAt = time.Now()
attachment.StatusID = ""
- if err := p.db.UpdateByPrimaryKey(ctx, attachment); err != nil {
+ if err := p.db.UpdateByPrimaryKey(ctx, attachment, updatingColumns...); err != nil {
return nil, gtserror.NewErrorNotFound(fmt.Errorf("db error updating attachment: %s", err))
}
diff --git a/internal/processing/media/unattach_test.go b/internal/processing/media/unattach_test.go
index 60efc2688..7572741ac 100644
--- a/internal/processing/media/unattach_test.go
+++ b/internal/processing/media/unattach_test.go
@@ -30,7 +30,7 @@ type UnattachTestSuite struct {
MediaStandardTestSuite
}
-func (suite *GetFileTestSuite) TestUnattachMedia() {
+func (suite *UnattachTestSuite) TestUnattachMedia() {
ctx := context.Background()
testAttachment := suite.testAttachments["admin_account_status_1_attachment_1"]
diff --git a/internal/processing/media/update.go b/internal/processing/media/update.go
index 116588a48..b8177eeb4 100644
--- a/internal/processing/media/update.go
+++ b/internal/processing/media/update.go
@@ -44,11 +44,11 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, media
return nil, gtserror.NewErrorNotFound(errors.New("attachment not owned by requesting account"))
}
+ updatingColumns := []string{}
+
if form.Description != nil {
attachment.Description = text.SanitizePlaintext(*form.Description)
- if err := p.db.UpdateByPrimaryKey(ctx, attachment); err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("database error updating description: %s", err))
- }
+ updatingColumns = append(updatingColumns, "description")
}
if form.Focus != nil {
@@ -58,9 +58,11 @@ func (p *processor) Update(ctx context.Context, account *gtsmodel.Account, media
}
attachment.FileMeta.Focus.X = focusx
attachment.FileMeta.Focus.Y = focusy
- if err := p.db.UpdateByPrimaryKey(ctx, attachment); err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("database error updating focus: %s", err))
- }
+ updatingColumns = append(updatingColumns, "focus_x", "focus_y")
+ }
+
+ if err := p.db.UpdateByPrimaryKey(ctx, attachment, updatingColumns...); err != nil {
+ return nil, gtserror.NewErrorInternalError(fmt.Errorf("database error updating media: %s", err))
}
a, err := p.tc.AttachmentToAPIAttachment(ctx, attachment)
diff --git a/internal/processing/status/create.go b/internal/processing/status/create.go
index 2c509809a..fef857c7c 100644
--- a/internal/processing/status/create.go
+++ b/internal/processing/status/create.go
@@ -40,18 +40,21 @@ func (p *processor) Create(ctx context.Context, account *gtsmodel.Account, appli
return nil, gtserror.NewErrorInternalError(err)
}
+ local := true
+ sensitive := form.Sensitive
+
newStatus := &gtsmodel.Status{
ID: thisStatusID,
URI: accountURIs.StatusesURI + "/" + thisStatusID,
URL: accountURIs.StatusesURL + "/" + thisStatusID,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
- Local: true,
+ Local: &local,
AccountID: account.ID,
AccountURI: account.URI,
ContentWarning: text.SanitizePlaintext(form.SpoilerText),
ActivityStreamsType: ap.ObjectNote,
- Sensitive: form.Sensitive,
+ Sensitive: &sensitive,
Language: form.Language,
CreatedWithApplicationID: application.ID,
Text: form.Status,
diff --git a/internal/processing/status/fave.go b/internal/processing/status/fave.go
index 1b40d9da1..f80d65358 100644
--- a/internal/processing/status/fave.go
+++ b/internal/processing/status/fave.go
@@ -49,7 +49,7 @@ func (p *processor) Fave(ctx context.Context, requestingAccount *gtsmodel.Accoun
if !visible {
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
}
- if !targetStatus.Likeable {
+ if !*targetStatus.Likeable {
return nil, gtserror.NewErrorForbidden(errors.New("status is not faveable"))
}
diff --git a/internal/processing/status/util.go b/internal/processing/status/util.go
index 64b496673..5e961e2ea 100644
--- a/internal/processing/status/util.go
+++ b/internal/processing/status/util.go
@@ -98,10 +98,10 @@ func (p *processor) ProcessVisibility(ctx context.Context, form *apimodel.Advanc
}
status.Visibility = vis
- status.Federated = federated
- status.Boostable = boostable
- status.Replyable = replyable
- status.Likeable = likeable
+ status.Federated = &federated
+ status.Boostable = &boostable
+ status.Replyable = &replyable
+ status.Likeable = &likeable
return nil
}
@@ -128,7 +128,7 @@ func (p *processor) ProcessReplyToID(ctx context.Context, form *apimodel.Advance
err := fmt.Errorf("db error fetching status with id %s: %s", form.InReplyToID, err)
return gtserror.NewErrorInternalError(err)
}
- if !repliedStatus.Replyable {
+ if !*repliedStatus.Replyable {
err := fmt.Errorf("status with id %s is marked as not replyable", form.InReplyToID)
return gtserror.NewErrorForbidden(err, err.Error())
}
diff --git a/internal/processing/user/changepassword.go b/internal/processing/user/changepassword.go
index 50c7a7517..ddfec6898 100644
--- a/internal/processing/user/changepassword.go
+++ b/internal/processing/user/changepassword.go
@@ -20,6 +20,7 @@ package user
import (
"context"
+ "time"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
@@ -42,7 +43,9 @@ func (p *processor) ChangePassword(ctx context.Context, user *gtsmodel.User, old
}
user.EncryptedPassword = string(newPasswordHash)
- if err := p.db.UpdateByPrimaryKey(ctx, user); err != nil {
+ user.UpdatedAt = time.Now()
+
+ if err := p.db.UpdateByPrimaryKey(ctx, user, "encrypted_password", "updated_at"); err != nil {
return gtserror.NewErrorInternalError(err, "database error")
}
diff --git a/internal/processing/user/emailconfirm.go b/internal/processing/user/emailconfirm.go
index eccaae5ec..6bffce7d9 100644
--- a/internal/processing/user/emailconfirm.go
+++ b/internal/processing/user/emailconfirm.go
@@ -71,12 +71,13 @@ func (p *processor) SendConfirmEmail(ctx context.Context, user *gtsmodel.User, u
}
// email sent, now we need to update the user entry with the token we just sent them
+ updatingColumns := []string{"confirmation_sent_at", "confirmation_token", "last_emailed_at", "updated_at"}
user.ConfirmationSentAt = time.Now()
user.ConfirmationToken = confirmationToken
user.LastEmailedAt = time.Now()
user.UpdatedAt = time.Now()
- if err := p.db.UpdateByPrimaryKey(ctx, user); err != nil {
+ if err := p.db.UpdateByPrimaryKey(ctx, user, updatingColumns...); err != nil {
return fmt.Errorf("SendConfirmEmail: error updating user entry after email sent: %s", err)
}
@@ -118,13 +119,14 @@ func (p *processor) ConfirmEmail(ctx context.Context, token string) (*gtsmodel.U
}
// mark the user's email address as confirmed + remove the unconfirmed address and the token
+ updatingColumns := []string{"email", "unconfirmed_email", "confirmed_at", "confirmation_token", "updated_at"}
user.Email = user.UnconfirmedEmail
user.UnconfirmedEmail = ""
user.ConfirmedAt = time.Now()
user.ConfirmationToken = ""
user.UpdatedAt = time.Now()
- if err := p.db.UpdateByPrimaryKey(ctx, user); err != nil {
+ if err := p.db.UpdateByPrimaryKey(ctx, user, updatingColumns...); err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
diff --git a/internal/processing/user/emailconfirm_test.go b/internal/processing/user/emailconfirm_test.go
index 6f22306a1..87aff9756 100644
--- a/internal/processing/user/emailconfirm_test.go
+++ b/internal/processing/user/emailconfirm_test.go
@@ -67,13 +67,14 @@ func (suite *EmailConfirmTestSuite) TestConfirmEmail() {
user := suite.testUsers["local_account_1"]
// set a bunch of stuff on the user as though zork hasn't been confirmed yet, but has had an email sent 5 minutes ago
+ updatingColumns := []string{"unconfirmed_email", "email", "confirmed_at", "confirmation_sent_at", "confirmation_token"}
user.UnconfirmedEmail = "some.email@example.org"
user.Email = ""
user.ConfirmedAt = time.Time{}
user.ConfirmationSentAt = time.Now().Add(-5 * time.Minute)
user.ConfirmationToken = "1d1aa44b-afa4-49c8-ac4b-eceb61715cc6"
- err := suite.db.UpdateByPrimaryKey(ctx, user)
+ err := suite.db.UpdateByPrimaryKey(ctx, user, updatingColumns...)
suite.NoError(err)
// confirm with the token set above
@@ -94,13 +95,14 @@ func (suite *EmailConfirmTestSuite) TestConfirmEmailOldToken() {
user := suite.testUsers["local_account_1"]
// set a bunch of stuff on the user as though zork hasn't been confirmed yet, but has had an email sent 8 days ago
+ updatingColumns := []string{"unconfirmed_email", "email", "confirmed_at", "confirmation_sent_at", "confirmation_token"}
user.UnconfirmedEmail = "some.email@example.org"
user.Email = ""
user.ConfirmedAt = time.Time{}
user.ConfirmationSentAt = time.Now().Add(-192 * time.Hour)
user.ConfirmationToken = "1d1aa44b-afa4-49c8-ac4b-eceb61715cc6"
- err := suite.db.UpdateByPrimaryKey(ctx, user)
+ err := suite.db.UpdateByPrimaryKey(ctx, user, updatingColumns...)
suite.NoError(err)
// confirm with the token set above
diff --git a/internal/processing/user/user_test.go b/internal/processing/user/user_test.go
index 007a5f8ce..56947f69a 100644
--- a/internal/processing/user/user_test.go
+++ b/internal/processing/user/user_test.go
@@ -40,8 +40,8 @@ type UserStandardTestSuite struct {
}
func (suite *UserStandardTestSuite) SetupTest() {
- testrig.InitTestLog()
testrig.InitTestConfig()
+ testrig.InitTestLog()
suite.db = testrig.NewTestDB()
suite.sentEmails = make(map[string]string)
diff --git a/internal/trans/model/account.go b/internal/trans/model/account.go
index 12d54a06f..1687d7676 100644
--- a/internal/trans/model/account.go
+++ b/internal/trans/model/account.go
@@ -34,7 +34,7 @@ type Account struct {
Domain string `json:"domain,omitempty" bun:",nullzero"`
HeaderRemoteURL string `json:"headerRemoteURL,omitempty" bun:",nullzero"`
AvatarRemoteURL string `json:"avatarRemoteURL,omitempty" bun:",nullzero"`
- Locked bool `json:"locked"`
+ Locked *bool `json:"locked" bun:",nullzero,notnull,default:true"`
Language string `json:"language,omitempty" bun:",nullzero"`
URI string `json:"uri" bun:",nullzero"`
URL string `json:"url" bun:",nullzero"`
diff --git a/internal/trans/model/domainblock.go b/internal/trans/model/domainblock.go
index 48cebb4aa..5e0006bd7 100644
--- a/internal/trans/model/domainblock.go
+++ b/internal/trans/model/domainblock.go
@@ -29,6 +29,6 @@ type DomainBlock struct {
CreatedByAccountID string `json:"createdByAccountID" bun:",nullzero"`
PrivateComment string `json:"privateComment,omitempty" bun:",nullzero"`
PublicComment string `json:"publicComment,omitempty" bun:",nullzero"`
- Obfuscate bool `json:"obfuscate" bun:",nullzero"`
+ Obfuscate *bool `json:"obfuscate" bun:",nullzero,notnull,default:false"`
SubscriptionID string `json:"subscriptionID,omitempty" bun:",nullzero"`
}
diff --git a/internal/trans/model/user.go b/internal/trans/model/user.go
index 317b4debf..09e7a25a3 100644
--- a/internal/trans/model/user.go
+++ b/internal/trans/model/user.go
@@ -41,10 +41,10 @@ type User struct {
ConfirmationSentAt *time.Time `json:"confirmationTokenSentAt,omitempty" bun:",nullzero"`
ConfirmedAt *time.Time `json:"confirmedAt,omitempty" bun:",nullzero"`
UnconfirmedEmail string `json:"unconfirmedEmail,omitempty" bun:",nullzero"`
- Moderator bool `json:"moderator"`
- Admin bool `json:"admin"`
- Disabled bool `json:"disabled"`
- Approved bool `json:"approved"`
+ Moderator *bool `json:"moderator" bun:",nullzero,notnull,default:false"`
+ Admin *bool `json:"admin" bun:",nullzero,notnull,default:false"`
+ Disabled *bool `json:"disabled" bun:",nullzero,notnull,default:false"`
+ Approved *bool `json:"approved" bun:",nullzero,notnull,default:false"`
ResetPasswordToken string `json:"resetPasswordToken,omitempty" bun:",nullzero"`
ResetPasswordSentAt *time.Time `json:"resetPasswordSentAt,omitempty" bun:",nullzero"`
}
diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go
index e30608150..7ec45335d 100644
--- a/internal/typeutils/astointernal.go
+++ b/internal/typeutils/astointernal.go
@@ -99,29 +99,46 @@ func (c *converter) ASRepresentationToAccount(ctx context.Context, accountable a
switch accountable.GetTypeName() {
case ap.ActorPerson, ap.ActorGroup, ap.ActorOrganization:
// people, groups, and organizations aren't bots
- acct.Bot = false
+ bot := false
+ acct.Bot = &bot
// apps and services are
case ap.ActorApplication, ap.ActorService:
- acct.Bot = true
+ bot := true
+ acct.Bot = &bot
default:
// we don't know what this is!
return nil, fmt.Errorf("type name %s not recognised or not convertible to ap.ActivityStreamsActor", accountable.GetTypeName())
}
acct.ActorType = accountable.GetTypeName()
+ // assume not memorial (todo)
+ memorial := false
+ acct.Memorial = &memorial
+
+ // assume not sensitive (todo)
+ sensitive := false
+ acct.Sensitive = &sensitive
+
+ // assume not hide collections (todo)
+ hideCollections := false
+ acct.HideCollections = &hideCollections
+
// locked aka manuallyApprovesFollowers
- acct.Locked = true // assume locked by default
+ locked := true
+ acct.Locked = &locked // assume locked by default
maf := accountable.GetActivityStreamsManuallyApprovesFollowers()
if maf != nil && maf.IsXMLSchemaBoolean() {
- acct.Locked = maf.Get()
+ locked = maf.Get()
+ acct.Locked = &locked
}
// discoverable
// default to false -- take custom value if it's set though
- acct.Discoverable = false
- discoverable, err := ap.ExtractDiscoverable(accountable)
+ discoverable := false
+ acct.Discoverable = &discoverable
+ d, err := ap.ExtractDiscoverable(accountable)
if err == nil {
- acct.Discoverable = discoverable
+ acct.Discoverable = &d
}
// url property
@@ -289,13 +306,20 @@ func (c *converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusab
// advanced visibility for this status
// TODO: a lot of work to be done here -- a new type needs to be created for this in go-fed/activity using ASTOOL
// for now we just set everything to true
- status.Federated = true
- status.Boostable = true
- status.Replyable = true
- status.Likeable = true
-
+ pinned := false
+ federated := true
+ boostable := true
+ replyable := true
+ likeable := true
+
+ status.Pinned = &pinned
+ status.Federated = &federated
+ status.Boostable = &boostable
+ status.Replyable = &replyable
+ status.Likeable = &likeable
// sensitive
- status.Sensitive = ap.ExtractSensitive(statusable)
+ sensitive := ap.ExtractSensitive(statusable)
+ status.Sensitive = &sensitive
// language
// we might be able to extract this from the contentMap field
diff --git a/internal/typeutils/astointernal_test.go b/internal/typeutils/astointernal_test.go
index dbd852d3f..7024018d6 100644
--- a/internal/typeutils/astointernal_test.go
+++ b/internal/typeutils/astointernal_test.go
@@ -51,9 +51,9 @@ func (suite *ASToInternalTestSuite) TestParsePerson() {
suite.Equal("Geoff Brando New Personson", acct.DisplayName)
suite.Equal("hey I'm a new person, your instance hasn't seen me yet uwu", acct.Note)
suite.Equal("https://unknown-instance.com/@brand_new_person", acct.URL)
- suite.True(acct.Discoverable)
+ suite.True(*acct.Discoverable)
suite.Equal("https://unknown-instance.com/users/brand_new_person#main-key", acct.PublicKeyURI)
- suite.False(acct.Locked)
+ suite.False(*acct.Locked)
}
func (suite *ASToInternalTestSuite) TestParsePublicStatus() {
@@ -145,10 +145,10 @@ func (suite *ASToInternalTestSuite) TestParseReplyWithMention() {
suite.Equal(inReplyToAccount.ID, status.InReplyToAccountID)
suite.Equal(inReplyToStatus.ID, status.InReplyToID)
suite.Equal(inReplyToStatus.URI, status.InReplyToURI)
- suite.True(status.Federated)
- suite.True(status.Boostable)
- suite.True(status.Replyable)
- suite.True(status.Likeable)
+ suite.True(*status.Federated)
+ suite.True(*status.Boostable)
+ suite.True(*status.Replyable)
+ suite.True(*status.Likeable)
suite.Equal(`<p><span class="h-card"><a href="http://localhost:8080/@the_mighty_zork" class="u-url mention">@<span>the_mighty_zork</span></a></span> nice there it is:</p><p><a href="http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/activity" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="ellipsis">social.pixie.town/users/f0x/st</span><span class="invisible">atuses/106221628567855262/activity</span></a></p>`, status.Content)
suite.Len(status.Mentions, 1)
m1 := status.Mentions[0]
@@ -177,9 +177,9 @@ func (suite *ASToInternalTestSuite) TestParseOwncastService() {
suite.Equal("https://owncast.example.org/logo/external", acct.HeaderRemoteURL)
suite.Equal("Rob's Owncast Server", acct.DisplayName)
suite.Equal("linux audio stuff ", acct.Note)
- suite.True(acct.Bot)
- suite.False(acct.Locked)
- suite.True(acct.Discoverable)
+ suite.True(*acct.Bot)
+ suite.False(*acct.Locked)
+ suite.True(*acct.Discoverable)
suite.Equal("https://owncast.example.org/federation/user/rgh", acct.URI)
suite.Equal("https://owncast.example.org/federation/user/rgh", acct.URL)
suite.Equal("https://owncast.example.org/federation/user/rgh/inbox", acct.InboxURI)
diff --git a/internal/typeutils/internal.go b/internal/typeutils/internal.go
index 0d49ea6b2..ce2c942fd 100644
--- a/internal/typeutils/internal.go
+++ b/internal/typeutils/internal.go
@@ -11,15 +11,18 @@ import (
)
func (c *converter) FollowRequestToFollow(ctx context.Context, f *gtsmodel.FollowRequest) *gtsmodel.Follow {
+ showReblogs := *f.ShowReblogs
+ notify := *f.Notify
+
return &gtsmodel.Follow{
ID: f.ID,
CreatedAt: f.CreatedAt,
UpdatedAt: f.UpdatedAt,
AccountID: f.AccountID,
TargetAccountID: f.TargetAccountID,
- ShowReblogs: f.ShowReblogs,
+ ShowReblogs: &showReblogs,
URI: f.URI,
- Notify: f.Notify,
+ Notify: &notify,
}
}
@@ -38,6 +41,13 @@ func (c *converter) StatusToBoost(ctx context.Context, s *gtsmodel.Status, boost
local = false
}
+ sensitive := *s.Sensitive
+ pinned := false // can't pin a boost
+ federated := *s.Federated
+ boostable := *s.Boostable
+ replyable := *s.Replyable
+ likeable := *s.Likeable
+
boostWrapperStatus := &gtsmodel.Status{
ID: boostWrapperStatusID,
URI: boostWrapperStatusURI,
@@ -46,7 +56,7 @@ func (c *converter) StatusToBoost(ctx context.Context, s *gtsmodel.Status, boost
// the boosted status is not created now, but the boost certainly is
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
- Local: local,
+ Local: &local,
AccountID: boostingAccount.ID,
AccountURI: boostingAccount.URI,
@@ -64,16 +74,17 @@ func (c *converter) StatusToBoost(ctx context.Context, s *gtsmodel.Status, boost
Content: s.Content,
ContentWarning: s.ContentWarning,
ActivityStreamsType: s.ActivityStreamsType,
- Sensitive: s.Sensitive,
+ Sensitive: &sensitive,
Language: s.Language,
Text: s.Text,
BoostOfID: s.ID,
BoostOfAccountID: s.AccountID,
Visibility: s.Visibility,
- Federated: s.Federated,
- Boostable: s.Boostable,
- Replyable: s.Replyable,
- Likeable: s.Likeable,
+ Pinned: &pinned,
+ Federated: &federated,
+ Boostable: &boostable,
+ Replyable: &replyable,
+ Likeable: &likeable,
// attach these here for convenience -- the boosted status/account won't go in the DB
// but they're needed in the processor and for the frontend. Since we have them, we can
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index bb611dd8f..43036c352 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -145,13 +145,13 @@ func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
// manuallyApprovesFollowers
// Will be shown as a locked account.
manuallyApprovesFollowersProp := streams.NewActivityStreamsManuallyApprovesFollowersProperty()
- manuallyApprovesFollowersProp.Set(a.Locked)
+ manuallyApprovesFollowersProp.Set(*a.Locked)
person.SetActivityStreamsManuallyApprovesFollowers(manuallyApprovesFollowersProp)
// discoverable
// Will be shown in the profile directory.
discoverableProp := streams.NewTootDiscoverableProperty()
- discoverableProp.Set(a.Discoverable)
+ discoverableProp.Set(*a.Discoverable)
person.SetTootDiscoverable(discoverableProp)
// devices
@@ -539,7 +539,7 @@ func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.A
// sensitive
sensitiveProp := streams.NewActivityStreamsSensitiveProperty()
- sensitiveProp.AppendXMLSchemaBoolean(s.Sensitive)
+ sensitiveProp.AppendXMLSchemaBoolean(*s.Sensitive)
status.SetActivityStreamsSensitive(sensitiveProp)
return status, nil
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index da124ce6c..7da54f979 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -60,7 +60,7 @@ func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmode
apiAccount.Source = &model.Source{
Privacy: c.VisToAPIVis(ctx, a.Privacy),
- Sensitive: a.Sensitive,
+ Sensitive: *a.Sensitive,
Language: a.Language,
StatusFormat: statusFormat,
Note: a.NoteRaw,
@@ -172,8 +172,8 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
Username: a.Username,
Acct: acct,
DisplayName: a.DisplayName,
- Locked: a.Locked,
- Bot: a.Bot,
+ Locked: *a.Locked,
+ Bot: *a.Bot,
CreatedAt: util.FormatISO8601(a.CreatedAt),
Note: a.Note,
URL: a.URL,
@@ -213,7 +213,7 @@ func (c *converter) AccountToAPIAccountBlocked(ctx context.Context, a *gtsmodel.
Username: a.Username,
Acct: acct,
DisplayName: a.DisplayName,
- Bot: a.Bot,
+ Bot: *a.Bot,
CreatedAt: util.FormatISO8601(a.CreatedAt),
URL: a.URL,
Suspended: suspended,
@@ -323,7 +323,7 @@ func (c *converter) EmojiToAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (mod
Shortcode: e.Shortcode,
URL: e.ImageURL,
StaticURL: e.ImageStaticURL,
- VisibleInPicker: e.VisibleInPicker,
+ VisibleInPicker: *e.VisibleInPicker,
Category: e.CategoryID,
}, nil
}
@@ -539,7 +539,7 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r
CreatedAt: util.FormatISO8601(s.CreatedAt),
InReplyToID: s.InReplyToID,
InReplyToAccountID: s.InReplyToAccountID,
- Sensitive: s.Sensitive,
+ Sensitive: *s.Sensitive,
SpoilerText: s.ContentWarning,
Visibility: c.VisToAPIVis(ctx, s.Visibility),
Language: s.Language,
@@ -552,7 +552,7 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r
Bookmarked: statusInteractions.Bookmarked,
Muted: statusInteractions.Muted,
Reblogged: statusInteractions.Reblogged,
- Pinned: s.Pinned,
+ Pinned: *s.Pinned,
Content: s.Content,
Application: apiApplication,
Account: apiAuthorAccount,
@@ -762,7 +762,7 @@ func (c *converter) DomainBlockToAPIDomainBlock(ctx context.Context, b *gtsmodel
// if we're exporting a domain block, return it with minimal information attached
if !export {
domainBlock.ID = b.ID
- domainBlock.Obfuscate = b.Obfuscate
+ domainBlock.Obfuscate = *b.Obfuscate
domainBlock.PrivateComment = b.PrivateComment
domainBlock.SubscriptionID = b.SubscriptionID
domainBlock.CreatedBy = b.CreatedByAccountID
diff --git a/internal/validate/account_test.go b/internal/validate/account_test.go
index e0dda8e16..1c318b4ef 100644
--- a/internal/validate/account_test.go
+++ b/internal/validate/account_test.go
@@ -28,6 +28,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyAccount() *gtsmodel.Account {
@@ -52,15 +53,15 @@ func happyAccount() *gtsmodel.Account {
DisplayName: "original zork (he/they)",
Fields: []gtsmodel.Field{},
Note: "hey yo this is my profile!",
- Memorial: false,
+ Memorial: testrig.FalseBool(),
AlsoKnownAs: "",
MovedToAccountID: "",
- Bot: false,
+ Bot: testrig.FalseBool(),
Reason: "I wanna be on this damned webbed site so bad! Please! Wow",
- Locked: false,
- Discoverable: true,
+ Locked: testrig.FalseBool(),
+ Discoverable: testrig.TrueBool(),
Privacy: gtsmodel.VisibilityPublic,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
StatusFormat: "plain",
URI: "http://localhost:8080/users/the_mighty_zork",
@@ -78,7 +79,7 @@ func happyAccount() *gtsmodel.Account {
SensitizedAt: time.Time{},
SilencedAt: time.Time{},
SuspendedAt: time.Time{},
- HideCollections: false,
+ HideCollections: testrig.FalseBool(),
SuspensionOrigin: "",
}
}
diff --git a/internal/validate/domainblock_test.go b/internal/validate/domainblock_test.go
index cb43a52a5..1406e539c 100644
--- a/internal/validate/domainblock_test.go
+++ b/internal/validate/domainblock_test.go
@@ -25,6 +25,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyDomainBlock() *gtsmodel.DomainBlock {
@@ -36,7 +37,7 @@ func happyDomainBlock() *gtsmodel.DomainBlock {
CreatedByAccountID: "01FEED79PRMVWPRMFHFQM8MJQN",
PrivateComment: "we don't like em",
PublicComment: "poo poo dudes",
- Obfuscate: false,
+ Obfuscate: testrig.FalseBool(),
SubscriptionID: "",
}
}
diff --git a/internal/validate/emoji_test.go b/internal/validate/emoji_test.go
index 4ea90f384..8bf5d65e0 100644
--- a/internal/validate/emoji_test.go
+++ b/internal/validate/emoji_test.go
@@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyEmoji() *gtsmodel.Emoji {
@@ -73,9 +74,9 @@ func happyEmoji() *gtsmodel.Emoji {
ImageFileSize: 1024,
ImageStaticFileSize: 256,
ImageUpdatedAt: time.Now(),
- Disabled: false,
+ Disabled: testrig.FalseBool(),
URI: "https://example.org/emojis/blob_test",
- VisibleInPicker: true,
+ VisibleInPicker: testrig.TrueBool(),
CategoryID: "01FEE47ZH70PWDSEAVBRFNX325",
}
}
diff --git a/internal/validate/mediaattachment_test.go b/internal/validate/mediaattachment_test.go
index 14a835014..491e974f9 100644
--- a/internal/validate/mediaattachment_test.go
+++ b/internal/validate/mediaattachment_test.go
@@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyMediaAttachment() *gtsmodel.MediaAttachment {
@@ -97,8 +98,8 @@ func happyMediaAttachment() *gtsmodel.MediaAttachment {
URL: "http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.jpeg",
RemoteURL: "",
},
- Avatar: false,
- Header: false,
+ Avatar: testrig.FalseBool(),
+ Header: testrig.FalseBool(),
}
}
diff --git a/internal/validate/status_test.go b/internal/validate/status_test.go
index cd3bc0f04..bebd3affd 100644
--- a/internal/validate/status_test.go
+++ b/internal/validate/status_test.go
@@ -26,6 +26,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyStatus() *gtsmodel.Status {
@@ -44,7 +45,7 @@ func happyStatus() *gtsmodel.Status {
Mentions: nil,
EmojiIDs: nil,
Emojis: nil,
- Local: true,
+ Local: testrig.TrueBool(),
AccountID: "01FEBBQ4KEP3824WW61MF52638",
Account: nil,
AccountURI: "https://example.org/users/test_user",
@@ -59,17 +60,17 @@ func happyStatus() *gtsmodel.Status {
BoostOfAccount: nil,
ContentWarning: "hello world test post",
Visibility: gtsmodel.VisibilityPublic,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "01FEBBZHF4GFVRXSJVXD0JTZZ2",
CreatedWithApplication: nil,
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
Text: "Test status! #hello",
- Pinned: false,
+ Pinned: testrig.FalseBool(),
}
}
@@ -127,7 +128,7 @@ func (suite *StatusValidateTestSuite) TestStatusApplicationID() {
err := validate.Struct(s)
suite.EqualError(err, "Key: 'Status.CreatedWithApplicationID' Error:Field validation for 'CreatedWithApplicationID' failed on the 'required_if' tag")
- s.Local = false
+ s.Local = testrig.FalseBool()
err = validate.Struct(s)
suite.NoError(err)
}
diff --git a/internal/validate/tag_test.go b/internal/validate/tag_test.go
index 451863570..506563a7c 100644
--- a/internal/validate/tag_test.go
+++ b/internal/validate/tag_test.go
@@ -25,6 +25,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyTag() *gtsmodel.Tag {
@@ -35,8 +36,8 @@ func happyTag() *gtsmodel.Tag {
URL: "https://example.org/tags/some_tag",
Name: "some_tag",
FirstSeenFromAccountID: "01FE91SR5P2GW06K3AJ98P72MT",
- Useable: true,
- Listable: true,
+ Useable: testrig.TrueBool(),
+ Listable: testrig.TrueBool(),
LastStatusAt: time.Now(),
}
}
diff --git a/internal/validate/user_test.go b/internal/validate/user_test.go
index f755ac42a..06c8bb0ac 100644
--- a/internal/validate/user_test.go
+++ b/internal/validate/user_test.go
@@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/validate"
+ "github.com/superseriousbusiness/gotosocial/testrig"
)
func happyUser() *gtsmodel.User {
@@ -54,10 +55,10 @@ func happyUser() *gtsmodel.User {
ConfirmedAt: time.Now(),
ConfirmationSentAt: time.Time{},
UnconfirmedEmail: "",
- Moderator: false,
- Admin: false,
- Disabled: false,
- Approved: true,
+ Moderator: testrig.FalseBool(),
+ Admin: testrig.FalseBool(),
+ Disabled: testrig.FalseBool(),
+ Approved: testrig.TrueBool(),
}
}
diff --git a/internal/visibility/statusboostable.go b/internal/visibility/statusboostable.go
index 60699875d..c502019ef 100644
--- a/internal/visibility/statusboostable.go
+++ b/internal/visibility/statusboostable.go
@@ -57,5 +57,5 @@ func (f *filter) StatusBoostable(ctx context.Context, targetStatus *gtsmodel.Sta
// otherwise, status is as boostable as it says it is
log.Trace("defaulting to status.boostable value")
- return targetStatus.Boostable, nil
+ return *targetStatus.Boostable, nil
}
diff --git a/internal/visibility/statushometimelineable_test.go b/internal/visibility/statushometimelineable_test.go
index 6161c52c0..ca80664dc 100644
--- a/internal/visibility/statushometimelineable_test.go
+++ b/internal/visibility/statushometimelineable_test.go
@@ -91,7 +91,7 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly(
Content: "didn't expect dog",
CreatedAt: testrig.TimeMustParse("2021-09-20T12:40:37+02:00"),
UpdatedAt: testrig.TimeMustParse("2021-09-20T12:40:37+02:00"),
- Local: false,
+ Local: testrig.FalseBool(),
AccountURI: "http://fossbros-anonymous.io/users/foss_satan",
AccountID: originalStatusParent.ID,
InReplyToID: "",
@@ -100,13 +100,13 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly(
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityFollowersOnly,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "",
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
if err := suite.db.PutStatus(ctx, originalStatus); err != nil {
@@ -125,7 +125,7 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly(
Content: "nbnbdy expects dog",
CreatedAt: testrig.TimeMustParse("2021-09-20T12:41:37+02:00"),
UpdatedAt: testrig.TimeMustParse("2021-09-20T12:41:37+02:00"),
- Local: false,
+ Local: testrig.FalseBool(),
AccountURI: "http://localhost:8080/users/the_mighty_zork",
AccountID: replyingAccount.ID,
InReplyToID: originalStatus.ID,
@@ -134,13 +134,13 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly(
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityFollowersOnly,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "",
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
if err := suite.db.PutStatus(ctx, firstReplyStatus); err != nil {
@@ -159,7 +159,7 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly(
Content: "*nobody",
CreatedAt: testrig.TimeMustParse("2021-09-20T12:42:37+02:00"),
UpdatedAt: testrig.TimeMustParse("2021-09-20T12:42:37+02:00"),
- Local: false,
+ Local: testrig.FalseBool(),
AccountURI: "http://localhost:8080/users/the_mighty_zork",
AccountID: replyingAccount.ID,
InReplyToID: firstReplyStatus.ID,
@@ -168,13 +168,13 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyFollowersOnly(
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityFollowersOnly,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "",
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
if err := suite.db.PutStatus(ctx, secondReplyStatus); err != nil {
@@ -204,7 +204,7 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyPublicAndUnloc
Content: "didn't expect dog",
CreatedAt: testrig.TimeMustParse("2021-09-20T12:40:37+02:00"),
UpdatedAt: testrig.TimeMustParse("2021-09-20T12:40:37+02:00"),
- Local: false,
+ Local: testrig.FalseBool(),
AccountURI: "http://fossbros-anonymous.io/users/foss_satan",
AccountID: originalStatusParent.ID,
InReplyToID: "",
@@ -213,13 +213,13 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyPublicAndUnloc
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityUnlocked,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "",
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
if err := suite.db.PutStatus(ctx, originalStatus); err != nil {
@@ -238,7 +238,7 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyPublicAndUnloc
Content: "nbnbdy expects dog",
CreatedAt: testrig.TimeMustParse("2021-09-20T12:41:37+02:00"),
UpdatedAt: testrig.TimeMustParse("2021-09-20T12:41:37+02:00"),
- Local: false,
+ Local: testrig.FalseBool(),
AccountURI: "http://localhost:8080/users/the_mighty_zork",
AccountID: replyingAccount.ID,
InReplyToID: originalStatus.ID,
@@ -247,13 +247,13 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyPublicAndUnloc
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityPublic,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "",
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
if err := suite.db.PutStatus(ctx, firstReplyStatus); err != nil {
@@ -272,7 +272,7 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyPublicAndUnloc
Content: "*nobody",
CreatedAt: testrig.TimeMustParse("2021-09-20T12:42:37+02:00"),
UpdatedAt: testrig.TimeMustParse("2021-09-20T12:42:37+02:00"),
- Local: false,
+ Local: testrig.FalseBool(),
AccountURI: "http://localhost:8080/users/the_mighty_zork",
AccountID: replyingAccount.ID,
InReplyToID: firstReplyStatus.ID,
@@ -281,13 +281,13 @@ func (suite *StatusStatusHometimelineableTestSuite) TestChainReplyPublicAndUnloc
BoostOfID: "",
ContentWarning: "",
Visibility: gtsmodel.VisibilityUnlocked,
- Sensitive: false,
+ Sensitive: testrig.FalseBool(),
Language: "en",
CreatedWithApplicationID: "",
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
+ Federated: testrig.TrueBool(),
+ Boostable: testrig.TrueBool(),
+ Replyable: testrig.TrueBool(),
+ Likeable: testrig.TrueBool(),
ActivityStreamsType: ap.ObjectNote,
}
if err := suite.db.PutStatus(ctx, secondReplyStatus); err != nil {
diff --git a/internal/visibility/statusvisible.go b/internal/visibility/statusvisible.go
index fc8bfeaaa..15d8544ad 100644
--- a/internal/visibility/statusvisible.go
+++ b/internal/visibility/statusvisible.go
@@ -79,7 +79,7 @@ func (f *filter) StatusVisible(ctx context.Context, targetStatus *gtsmodel.Statu
// if target user is disabled, not yet approved, or not confirmed then don't show the status
// (although in the latter two cases it's unlikely they posted a status yet anyway, but you never know!)
- if targetUser.Disabled || !targetUser.Approved || targetUser.ConfirmedAt.IsZero() {
+ if *targetUser.Disabled || !*targetUser.Approved || targetUser.ConfirmedAt.IsZero() {
l.Trace("target user is disabled, not approved, or not confirmed")
return false, nil
}
@@ -108,7 +108,7 @@ func (f *filter) StatusVisible(ctx context.Context, targetStatus *gtsmodel.Statu
return false, fmt.Errorf("StatusVisible: db error selecting user for local requesting account %s: %s", requestingAccount.ID, err)
}
// okay, user exists, so make sure it has full privileges/is confirmed/approved
- if requestingUser.Disabled || !requestingUser.Approved || requestingUser.ConfirmedAt.IsZero() {
+ if *requestingUser.Disabled || !*requestingUser.Approved || requestingUser.ConfirmedAt.IsZero() {
l.Trace("requesting account is local but corresponding user is either disabled, not approved, or not confirmed")
return false, nil
}