mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[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:
@@ -76,19 +76,21 @@ func (p *processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
showReblogs := true
|
||||
notify := false
|
||||
fr := >smodel.FollowRequest{
|
||||
ID: newFollowID,
|
||||
AccountID: requestingAccount.ID,
|
||||
TargetAccountID: form.ID,
|
||||
ShowReblogs: true,
|
||||
ShowReblogs: &showReblogs,
|
||||
URI: uris.GenerateURIForFollow(requestingAccount.Username, newFollowID),
|
||||
Notify: false,
|
||||
Notify: ¬ify,
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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 := >smodel.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")
|
||||
|
@@ -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))
|
||||
}
|
||||
}
|
||||
|
@@ -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")
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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 := >smodel.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)
|
||||
|
@@ -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))
|
||||
}
|
||||
|
||||
|
@@ -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))
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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))
|
||||
}
|
||||
|
||||
|
@@ -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"]
|
||||
|
@@ -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)
|
||||
|
@@ -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 := >smodel.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,
|
||||
|
@@ -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"))
|
||||
}
|
||||
|
||||
|
@@ -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())
|
||||
}
|
||||
|
@@ -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")
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user