create.go (3639B)
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 report 19 20 import ( 21 "context" 22 "errors" 23 "fmt" 24 25 "github.com/superseriousbusiness/gotosocial/internal/ap" 26 apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" 27 "github.com/superseriousbusiness/gotosocial/internal/db" 28 "github.com/superseriousbusiness/gotosocial/internal/gtserror" 29 "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 30 "github.com/superseriousbusiness/gotosocial/internal/id" 31 "github.com/superseriousbusiness/gotosocial/internal/messages" 32 "github.com/superseriousbusiness/gotosocial/internal/uris" 33 ) 34 35 // Create creates one user report / flag, using the provided form parameters. 36 func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form *apimodel.ReportCreateRequest) (*apimodel.Report, gtserror.WithCode) { 37 if account.ID == form.AccountID { 38 err := errors.New("cannot report your own account") 39 return nil, gtserror.NewErrorBadRequest(err, err.Error()) 40 } 41 42 // validate + fetch target account 43 targetAccount, err := p.state.DB.GetAccountByID(ctx, form.AccountID) 44 if err != nil { 45 if errors.Is(err, db.ErrNoEntries) { 46 err = fmt.Errorf("account with ID %s does not exist", form.AccountID) 47 return nil, gtserror.NewErrorBadRequest(err, err.Error()) 48 } 49 err = fmt.Errorf("db error fetching report target account: %w", err) 50 return nil, gtserror.NewErrorInternalError(err) 51 } 52 53 // fetch statuses by IDs given in the report form (noop if no statuses given) 54 statuses, err := p.state.DB.GetStatuses(ctx, form.StatusIDs) 55 if err != nil { 56 err = fmt.Errorf("db error fetching report target statuses: %w", err) 57 return nil, gtserror.NewErrorInternalError(err) 58 } 59 60 for _, s := range statuses { 61 if s.AccountID != form.AccountID { 62 err = fmt.Errorf("status with ID %s does not belong to account %s", s.ID, form.AccountID) 63 return nil, gtserror.NewErrorBadRequest(err, err.Error()) 64 } 65 } 66 67 reportID := id.NewULID() 68 report := >smodel.Report{ 69 ID: reportID, 70 URI: uris.GenerateURIForReport(reportID), 71 AccountID: account.ID, 72 Account: account, 73 TargetAccountID: form.AccountID, 74 TargetAccount: targetAccount, 75 Comment: form.Comment, 76 StatusIDs: form.StatusIDs, 77 Statuses: statuses, 78 Forwarded: &form.Forward, 79 } 80 81 if err := p.state.DB.PutReport(ctx, report); err != nil { 82 return nil, gtserror.NewErrorInternalError(err) 83 } 84 85 p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{ 86 APObjectType: ap.ObjectProfile, 87 APActivityType: ap.ActivityFlag, 88 GTSModel: report, 89 OriginAccount: account, 90 TargetAccount: targetAccount, 91 }) 92 93 apiReport, err := p.tc.ReportToAPIReport(ctx, report) 94 if err != nil { 95 err = fmt.Errorf("error converting report to frontend representation: %w", err) 96 return nil, gtserror.NewErrorInternalError(err) 97 } 98 99 return apiReport, nil 100 }