mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-30 08:16:15 -06:00
ensure that errors checking status visibility / converting aren't dropped
This commit is contained in:
parent
77b095a8c3
commit
480522da21
3 changed files with 100 additions and 66 deletions
|
|
@ -104,18 +104,20 @@ func (f *Filter) isStatusVisible(
|
|||
return false, nil
|
||||
}
|
||||
|
||||
if util.PtrOrValue(status.PendingApproval, false) {
|
||||
if util.PtrOrZero(status.PendingApproval) {
|
||||
// Use a different visibility heuristic
|
||||
// for pending approval statuses.
|
||||
return f.isPendingStatusVisible(ctx,
|
||||
return isPendingStatusVisible(
|
||||
requester, status,
|
||||
)
|
||||
), nil
|
||||
}
|
||||
|
||||
if requester == nil {
|
||||
// Use a different visibility
|
||||
// heuristic for unauthed requests.
|
||||
return f.isStatusVisibleUnauthed(ctx, status)
|
||||
return f.isStatusVisibleUnauthed(
|
||||
ctx, status,
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -210,45 +212,42 @@ func (f *Filter) isStatusVisible(
|
|||
}
|
||||
}
|
||||
|
||||
func (f *Filter) isPendingStatusVisible(
|
||||
_ context.Context,
|
||||
requester *gtsmodel.Account,
|
||||
status *gtsmodel.Status,
|
||||
) (bool, error) {
|
||||
// isPendingStatusVisible returns whether a status pending approval is visible to requester.
|
||||
func isPendingStatusVisible(requester *gtsmodel.Account, status *gtsmodel.Status) bool {
|
||||
if requester == nil {
|
||||
// Any old tom, dick, and harry can't
|
||||
// see pending-approval statuses,
|
||||
// no matter what their visibility.
|
||||
return false, nil
|
||||
return false
|
||||
}
|
||||
|
||||
if status.AccountID == requester.ID {
|
||||
// This is requester's status,
|
||||
// so they can always see it.
|
||||
return true, nil
|
||||
return true
|
||||
}
|
||||
|
||||
if status.InReplyToAccountID == requester.ID {
|
||||
// This status replies to requester,
|
||||
// so they can always see it (else
|
||||
// they can't approve it).
|
||||
return true, nil
|
||||
return true
|
||||
}
|
||||
|
||||
if status.BoostOfAccountID == requester.ID {
|
||||
// This status boosts requester,
|
||||
// so they can always see it.
|
||||
return true, nil
|
||||
return true
|
||||
}
|
||||
|
||||
// Nobody else can see this.
|
||||
return false, nil
|
||||
// Nobody else
|
||||
// can see this.
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *Filter) isStatusVisibleUnauthed(
|
||||
ctx context.Context,
|
||||
status *gtsmodel.Status,
|
||||
) (bool, error) {
|
||||
// isStatusVisibleUnauthed returns whether status is visible without any unauthenticated account.
|
||||
func (f *Filter) isStatusVisibleUnauthed(ctx context.Context, status *gtsmodel.Status) (bool, error) {
|
||||
|
||||
// For remote accounts, only show
|
||||
// Public statuses via the web.
|
||||
if status.Account.IsRemote() {
|
||||
|
|
@ -275,8 +274,7 @@ func (f *Filter) isStatusVisibleUnauthed(
|
|||
}
|
||||
}
|
||||
|
||||
webVisibility := status.Account.Settings.WebVisibility
|
||||
switch webVisibility {
|
||||
switch webvis := status.Account.Settings.WebVisibility; webvis {
|
||||
|
||||
// public_only: status must be Public.
|
||||
case gtsmodel.VisibilityPublic:
|
||||
|
|
@ -296,7 +294,7 @@ func (f *Filter) isStatusVisibleUnauthed(
|
|||
default:
|
||||
return false, gtserror.Newf(
|
||||
"unrecognized web visibility for account %s: %s",
|
||||
status.Account.ID, webVisibility,
|
||||
status.Account.ID, webvis,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing"
|
||||
statusfilter "github.com/superseriousbusiness/gotosocial/internal/filter/status"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/usermute"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
|
|
@ -174,14 +175,72 @@ func (p *Processor) GetAPIStatus(
|
|||
apiStatus *apimodel.Status,
|
||||
errWithCode gtserror.WithCode,
|
||||
) {
|
||||
apiStatus, err := p.converter.StatusToAPIStatus(ctx, target, requester, statusfilter.FilterContextNone, nil, nil)
|
||||
apiStatus, err := p.converter.StatusToAPIStatus(ctx,
|
||||
target,
|
||||
requester,
|
||||
statusfilter.FilterContextNone,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
err = gtserror.Newf("error converting status: %w", err)
|
||||
err := gtserror.Newf("error converting status: %w", err)
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
return apiStatus, nil
|
||||
}
|
||||
|
||||
// GetVisibleAPIStatuses converts a slice of statuses to API
|
||||
// model statuses, filtering according to visibility to requester
|
||||
// along with given filter context, filters and user mutes.
|
||||
func (p *Processor) GetVisibleAPIStatuses(
|
||||
ctx context.Context,
|
||||
requester *gtsmodel.Account,
|
||||
statuses []*gtsmodel.Status,
|
||||
filterContext statusfilter.FilterContext,
|
||||
filters []*gtsmodel.Filter,
|
||||
userMutes []*gtsmodel.UserMute,
|
||||
) []apimodel.Status {
|
||||
// Compile mutes to useable user mutes for type converter.
|
||||
compUserMutes := usermute.NewCompiledUserMuteList(userMutes)
|
||||
|
||||
// Iterate filtered statuses for conversion to API model.
|
||||
apiStatuses := make([]apimodel.Status, 0, len(statuses))
|
||||
for _, status := range statuses {
|
||||
|
||||
// Check whether status is visible to requester.
|
||||
visible, err := p.visFilter.StatusVisible(ctx,
|
||||
requester,
|
||||
status,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf(ctx, "error checking status visibility: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !visible {
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert to API status, taking mute / filter into account.
|
||||
apiStatus, err := p.converter.StatusToAPIStatus(ctx,
|
||||
status,
|
||||
requester,
|
||||
filterContext,
|
||||
filters,
|
||||
compUserMutes,
|
||||
)
|
||||
if err != nil && !errors.Is(err, statusfilter.ErrHideStatus) {
|
||||
log.Errorf(ctx, "error converting to api model: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Append converted status to return slice.
|
||||
apiStatuses = append(apiStatuses, *apiStatus)
|
||||
}
|
||||
|
||||
return apiStatuses
|
||||
}
|
||||
|
||||
// InvalidateTimelinedStatus is a shortcut function for invalidating the cached
|
||||
// representation one status in the home timeline and all list timelines of the
|
||||
// given accountID. It should only be called in cases where a status update
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
statusfilter "github.com/superseriousbusiness/gotosocial/internal/filter/status"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/filter/usermute"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
@ -308,22 +307,7 @@ func (p *Processor) ContextGet(
|
|||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
convert := func(
|
||||
ctx context.Context,
|
||||
status *gtsmodel.Status,
|
||||
requestingAccount *gtsmodel.Account,
|
||||
) (*apimodel.Status, error) {
|
||||
return p.converter.StatusToAPIStatus(
|
||||
ctx,
|
||||
status,
|
||||
requestingAccount,
|
||||
statusfilter.FilterContextThread,
|
||||
filters,
|
||||
usermute.NewCompiledUserMuteList(mutes),
|
||||
)
|
||||
}
|
||||
|
||||
// Retrieve the thread context.
|
||||
// Retrieve the full thread context.
|
||||
threadContext, errWithCode := p.contextGet(
|
||||
ctx,
|
||||
requester,
|
||||
|
|
@ -333,34 +317,27 @@ func (p *Processor) ContextGet(
|
|||
return nil, errWithCode
|
||||
}
|
||||
|
||||
apiContext := &apimodel.ThreadContext{
|
||||
Ancestors: make([]apimodel.Status, 0, len(threadContext.ancestors)),
|
||||
Descendants: make([]apimodel.Status, 0, len(threadContext.descendants)),
|
||||
}
|
||||
var apiContext apimodel.ThreadContext
|
||||
|
||||
// Convert ancestors + filter
|
||||
// out ones that aren't visible.
|
||||
for _, status := range threadContext.ancestors {
|
||||
if v, err := p.visFilter.StatusVisible(ctx, requester, status); err == nil && v {
|
||||
status, err := convert(ctx, status, requester)
|
||||
if err == nil {
|
||||
apiContext.Ancestors = append(apiContext.Ancestors, *status)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert and filter the thread context ancestors.
|
||||
apiContext.Ancestors = p.c.GetVisibleAPIStatuses(ctx,
|
||||
requester,
|
||||
threadContext.ancestors,
|
||||
statusfilter.FilterContextThread,
|
||||
filters,
|
||||
mutes,
|
||||
)
|
||||
|
||||
// Convert descendants + filter
|
||||
// out ones that aren't visible.
|
||||
for _, status := range threadContext.descendants {
|
||||
if v, err := p.visFilter.StatusVisible(ctx, requester, status); err == nil && v {
|
||||
status, err := convert(ctx, status, requester)
|
||||
if err == nil {
|
||||
apiContext.Descendants = append(apiContext.Descendants, *status)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert and filter the thread context descendants
|
||||
apiContext.Descendants = p.c.GetVisibleAPIStatuses(ctx,
|
||||
requester,
|
||||
threadContext.descendants,
|
||||
statusfilter.FilterContextThread,
|
||||
filters,
|
||||
mutes,
|
||||
)
|
||||
|
||||
return apiContext, nil
|
||||
return &apiContext, nil
|
||||
}
|
||||
|
||||
// WebContextGet is like ContextGet, but is explicitly
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue