Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bugfix] Reorder web view logic, other small fixes #1954

Merged
merged 1 commit into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions internal/api/util/parsequery.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ const (
SearchResolveKey = "resolve"
SearchTypeKey = "type"

/* Web endpoint keys */

WebUsernameKey = "username"
WebStatusIDKey = "status"

/* Domain block keys */

DomainBlockExportKey = "export"
Expand Down Expand Up @@ -75,6 +80,14 @@ func ParseLocal(value string, defaultValue bool) (bool, gtserror.WithCode) {
return parseBool(value, defaultValue, LocalKey)
}

func ParseMaxID(value string, defaultValue string) string {
if value == "" {
return defaultValue
}

return value
}

func ParseSearchExcludeUnreviewed(value string, defaultValue bool) (bool, gtserror.WithCode) {
return parseBool(value, defaultValue, SearchExcludeUnreviewedKey)
}
Expand Down Expand Up @@ -133,6 +146,26 @@ func ParseSearchQuery(value string) (string, gtserror.WithCode) {
return value, nil
}

func ParseWebUsername(value string) (string, gtserror.WithCode) {
key := WebUsernameKey

if value == "" {
return "", requiredError(key)
}

return value, nil
}

func ParseWebStatusID(value string) (string, gtserror.WithCode) {
key := WebStatusIDKey

if value == "" {
return "", requiredError(key)
}

return value, nil
}

/*
Internal functions
*/
Expand Down
2 changes: 1 addition & 1 deletion internal/federation/dereferencing/dereferencer.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type deref struct {
derefEmojis map[string]*media.ProcessingEmoji
derefEmojisMu mutexes.Mutex
handshakes map[string][]*url.URL
handshakeSync sync.Mutex // mutex to lock/unlock when checking or updating the handshakes map
handshakesMu sync.Mutex // mutex to lock/unlock when checking or updating the handshakes map
}

// NewDereferencer returns a Dereferencer initialized with the given parameters.
Expand Down
47 changes: 31 additions & 16 deletions internal/federation/dereferencing/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,68 +22,83 @@ import (
)

func (d *deref) Handshaking(username string, remoteAccountID *url.URL) bool {
d.handshakeSync.Lock()
defer d.handshakeSync.Unlock()
d.handshakesMu.Lock()
defer d.handshakesMu.Unlock()

if d.handshakes == nil {
// handshakes isn't even initialized yet so we can't be handshaking with anyone
// Handshakes isn't even initialized yet,
// so we can't be handshaking with anyone.
return false
}

remoteIDs, ok := d.handshakes[username]
if !ok {
// user isn't handshaking with anyone, bail
// Given username isn't
// handshaking with anyone.
return false
}

for _, id := range remoteIDs {
if id.String() == remoteAccountID.String() {
// we are currently handshaking with the remote account, yep
// We are currently handshaking
// with the remote account.
return true
}
}

// didn't find it which means we're not handshaking
// No results: we're not handshaking
// with the remote account.
return false
}

func (d *deref) startHandshake(username string, remoteAccountID *url.URL) {
d.handshakeSync.Lock()
defer d.handshakeSync.Unlock()
d.handshakesMu.Lock()
defer d.handshakesMu.Unlock()

remoteIDs, ok := d.handshakes[username]
if !ok {
// there was nothing in there yet, so just add this entry and return
// No handshakes were stored yet,
// so just add this entry and return.
d.handshakes[username] = []*url.URL{remoteAccountID}
return
}

// add the remote ID to the slice
// Add the remote account ID to the slice.
remoteIDs = append(remoteIDs, remoteAccountID)
d.handshakes[username] = remoteIDs
}

func (d *deref) stopHandshake(username string, remoteAccountID *url.URL) {
d.handshakeSync.Lock()
defer d.handshakeSync.Unlock()
d.handshakesMu.Lock()
defer d.handshakesMu.Unlock()

remoteIDs, ok := d.handshakes[username]
if !ok {
// No handshake was in progress,
// so there's nothing to stop.
return
}

newRemoteIDs := []*url.URL{}
// Generate a new remoteIDs slice that
// doesn't contain the removed entry.
var (
remoteAccountIDStr = remoteAccountID.String()
newRemoteIDs = make([]*url.URL, 0, len(remoteIDs)-1)
)

for _, id := range remoteIDs {
if id.String() != remoteAccountID.String() {
if id.String() != remoteAccountIDStr {
newRemoteIDs = append(newRemoteIDs, id)
}
}

if len(newRemoteIDs) == 0 {
// there are no handshakes so just remove this user entry from the map and save a few bytes
// There are no handshakes remaining,
// so just remove this username's slice
// from the map and save a few bytes.
delete(d.handshakes, username)
} else {
// there are still other handshakes ongoing
// There are still other handshakes ongoing.
d.handshakes[username] = newRemoteIDs
}
}
6 changes: 6 additions & 0 deletions internal/processing/account/statuses.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,9 @@ func (p *Processor) WebStatusesGet(ctx context.Context, targetAccountID string,
NextMaxIDValue: nextMaxIDValue,
})
}

// PinnedStatusesGet is a shortcut for getting just an account's pinned statuses.
// Under the hood, it just calls StatusesGet using mostly default parameters.
func (p *Processor) PinnedStatusesGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.PageableResponse, gtserror.WithCode) {
return p.StatusesGet(ctx, requestingAccount, targetAccountID, 0, false, false, "", "", true, false, false)
}
48 changes: 34 additions & 14 deletions internal/processing/fedi/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,61 @@ package fedi

import (
"context"
"errors"
"fmt"
"net/url"

"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)

func (p *Processor) authenticate(ctx context.Context, requestedUsername string) (requestedAccount, requestingAccount *gtsmodel.Account, errWithCode gtserror.WithCode) {
func (p *Processor) authenticate(ctx context.Context, requestedUsername string) (
*gtsmodel.Account, // requestedAccount
*gtsmodel.Account, // requestingAccount
gtserror.WithCode,
) {
// Get LOCAL account with the requested username.
requestedAccount, err := p.state.DB.GetAccountByUsernameDomain(ctx, requestedUsername, "")
if err != nil {
errWithCode = gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
return
if !errors.Is(err, db.ErrNoEntries) {
// Real db error.
err = gtserror.Newf("db error getting account %s: %w", requestedUsername, err)
return nil, nil, gtserror.NewErrorInternalError(err)
}

// Account just not found in the db.
return nil, nil, gtserror.NewErrorNotFound(err)
}

var requestingAccountURI *url.URL
requestingAccountURI, errWithCode = p.federator.AuthenticateFederatedRequest(ctx, requestedUsername)
// Ensure request signed, and use signature URI to
// get requesting account, dereferencing if necessary.
requestingAccountURI, errWithCode := p.federator.AuthenticateFederatedRequest(ctx, requestedUsername)
if errWithCode != nil {
return
return nil, nil, errWithCode
}

if requestingAccount, _, err = p.federator.GetAccountByURI(gtscontext.SetFastFail(ctx), requestedUsername, requestingAccountURI); err != nil {
errWithCode = gtserror.NewErrorUnauthorized(err)
return
requestingAccount, _, err := p.federator.GetAccountByURI(
gtscontext.SetFastFail(ctx),
requestedUsername,
requestingAccountURI,
)
if err != nil {
err = gtserror.Newf("error getting account %s: %w", requestingAccountURI, err)
return nil, nil, gtserror.NewErrorUnauthorized(err)
}

// Ensure no block exists between requester + requested.
blocked, err := p.state.DB.IsEitherBlocked(ctx, requestedAccount.ID, requestingAccount.ID)
if err != nil {
errWithCode = gtserror.NewErrorInternalError(err)
return
err = gtserror.Newf("db error getting checking block: %w", err)
return nil, nil, gtserror.NewErrorInternalError(err)
}

if blocked {
errWithCode = gtserror.NewErrorUnauthorized(fmt.Errorf("block exists between accounts %s and %s", requestedAccount.ID, requestingAccount.ID))
err = fmt.Errorf("block exists between accounts %s and %s", requestedAccount.ID, requestingAccount.ID)
return nil, nil, gtserror.NewErrorUnauthorized(err)
}

return
return requestedAccount, requestingAccount, nil
}
12 changes: 8 additions & 4 deletions internal/processing/fedi/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)

// StatusGet handles the getting of a fedi/activitypub representation of a particular status, performing appropriate
// authentication before returning a JSON serializable interface to the caller.
// StatusGet handles the getting of a fedi/activitypub representation of a local status.
// It performs appropriate authentication before returning a JSON serializable interface.
func (p *Processor) StatusGet(ctx context.Context, requestedUsername string, requestedStatusID string) (interface{}, gtserror.WithCode) {
// Authenticate using http signature.
requestedAccount, requestingAccount, errWithCode := p.authenticate(ctx, requestedUsername)
if errWithCode != nil {
return nil, errWithCode
Expand All @@ -41,15 +42,18 @@ func (p *Processor) StatusGet(ctx context.Context, requestedUsername string, req
}

if status.AccountID != requestedAccount.ID {
return nil, gtserror.NewErrorNotFound(fmt.Errorf("status with id %s does not belong to account with id %s", status.ID, requestedAccount.ID))
err := fmt.Errorf("status with id %s does not belong to account with id %s", status.ID, requestedAccount.ID)
return nil, gtserror.NewErrorNotFound(err)
}

visible, err := p.filter.StatusVisible(ctx, requestingAccount, status)
if err != nil {
return nil, gtserror.NewErrorInternalError(err)
}

if !visible {
return nil, gtserror.NewErrorNotFound(fmt.Errorf("status with id %s not visible to user with id %s", status.ID, requestingAccount.ID))
err := fmt.Errorf("status with id %s not visible to user with id %s", status.ID, requestingAccount.ID)
return nil, gtserror.NewErrorNotFound(err)
}

asStatus, err := p.tc.StatusToAS(ctx, status)
Expand Down
Loading