[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
This commit is contained in:
tobi
2022-08-15 12:35:05 +02:00
committed by GitHub
parent 52fe681ba2
commit ac6ed3d939
376 changed files with 337942 additions and 298092 deletions

View File

@@ -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))
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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")

View File

@@ -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))
}
}

View File

@@ -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")
}

View File

@@ -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
}

View File

@@ -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,
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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))
}

View File

@@ -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))
}

View File

@@ -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)

View File

@@ -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))
}

View File

@@ -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"]

View File

@@ -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)

View File

@@ -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,

View File

@@ -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"))
}

View File

@@ -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())
}

View File

@@ -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")
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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)