gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

get.go (4602B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package account
     19 
     20 import (
     21 	"context"
     22 	"errors"
     23 	"fmt"
     24 	"net/url"
     25 
     26 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     27 	"github.com/superseriousbusiness/gotosocial/internal/db"
     28 	"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
     29 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     30 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     31 	"github.com/superseriousbusiness/gotosocial/internal/log"
     32 )
     33 
     34 // Get processes the given request for account information.
     35 func (p *Processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, gtserror.WithCode) {
     36 	targetAccount, err := p.state.DB.GetAccountByID(ctx, targetAccountID)
     37 	if err != nil {
     38 		if errors.Is(err, db.ErrNoEntries) {
     39 			return nil, gtserror.NewErrorNotFound(errors.New("account not found"))
     40 		}
     41 		return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error: %w", err))
     42 	}
     43 
     44 	return p.getFor(ctx, requestingAccount, targetAccount)
     45 }
     46 
     47 // GetLocalByUsername processes the given request for account information targeting a local account by username.
     48 func (p *Processor) GetLocalByUsername(ctx context.Context, requestingAccount *gtsmodel.Account, username string) (*apimodel.Account, gtserror.WithCode) {
     49 	targetAccount, err := p.state.DB.GetAccountByUsernameDomain(ctx, username, "")
     50 	if err != nil {
     51 		if errors.Is(err, db.ErrNoEntries) {
     52 			return nil, gtserror.NewErrorNotFound(errors.New("account not found"))
     53 		}
     54 		return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error: %w", err))
     55 	}
     56 
     57 	return p.getFor(ctx, requestingAccount, targetAccount)
     58 }
     59 
     60 // GetCustomCSSForUsername returns custom css for the given local username.
     61 func (p *Processor) GetCustomCSSForUsername(ctx context.Context, username string) (string, gtserror.WithCode) {
     62 	customCSS, err := p.state.DB.GetAccountCustomCSSByUsername(ctx, username)
     63 	if err != nil {
     64 		if errors.Is(err, db.ErrNoEntries) {
     65 			return "", gtserror.NewErrorNotFound(errors.New("account not found"))
     66 		}
     67 		return "", gtserror.NewErrorInternalError(fmt.Errorf("db error: %w", err))
     68 	}
     69 
     70 	return customCSS, nil
     71 }
     72 
     73 func (p *Processor) getFor(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (*apimodel.Account, gtserror.WithCode) {
     74 	var err error
     75 
     76 	if requestingAccount != nil {
     77 		blocked, err := p.state.DB.IsEitherBlocked(ctx, requestingAccount.ID, targetAccount.ID)
     78 		if err != nil {
     79 			return nil, gtserror.NewErrorInternalError(fmt.Errorf("error checking account block: %w", err))
     80 		}
     81 
     82 		if blocked {
     83 			apiAccount, err := p.tc.AccountToAPIAccountBlocked(ctx, targetAccount)
     84 			if err != nil {
     85 				return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting account: %w", err))
     86 			}
     87 			return apiAccount, nil
     88 		}
     89 	}
     90 
     91 	if targetAccount.Domain != "" {
     92 		targetAccountURI, err := url.Parse(targetAccount.URI)
     93 		if err != nil {
     94 			return nil, gtserror.NewErrorInternalError(fmt.Errorf("error parsing url %s: %w", targetAccount.URI, err))
     95 		}
     96 
     97 		// Perform a last-minute fetch of target account to ensure remote account header / avatar is cached.
     98 		latest, _, err := p.federator.GetAccountByURI(gtscontext.SetFastFail(ctx), requestingAccount.Username, targetAccountURI)
     99 		if err != nil {
    100 			log.Errorf(ctx, "error fetching latest target account: %v", err)
    101 		} else {
    102 			// Use latest account model.
    103 			targetAccount = latest
    104 		}
    105 	}
    106 
    107 	var apiAccount *apimodel.Account
    108 
    109 	if requestingAccount != nil && targetAccount.ID == requestingAccount.ID {
    110 		apiAccount, err = p.tc.AccountToAPIAccountSensitive(ctx, targetAccount)
    111 	} else {
    112 		apiAccount, err = p.tc.AccountToAPIAccountPublic(ctx, targetAccount)
    113 	}
    114 	if err != nil {
    115 		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting account: %w", err))
    116 	}
    117 
    118 	return apiAccount, nil
    119 }