report.go (5053B)
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 admin 19 20 import ( 21 "context" 22 "fmt" 23 "strconv" 24 "time" 25 26 "github.com/superseriousbusiness/gotosocial/internal/ap" 27 apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" 28 "github.com/superseriousbusiness/gotosocial/internal/db" 29 "github.com/superseriousbusiness/gotosocial/internal/gtserror" 30 "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" 31 "github.com/superseriousbusiness/gotosocial/internal/messages" 32 "github.com/superseriousbusiness/gotosocial/internal/util" 33 ) 34 35 // ReportsGet returns all reports stored on this instance, with the given parameters. 36 func (p *Processor) ReportsGet( 37 ctx context.Context, 38 account *gtsmodel.Account, 39 resolved *bool, 40 accountID string, 41 targetAccountID string, 42 maxID string, 43 sinceID string, 44 minID string, 45 limit int, 46 ) (*apimodel.PageableResponse, gtserror.WithCode) { 47 reports, err := p.state.DB.GetReports(ctx, resolved, accountID, targetAccountID, maxID, sinceID, minID, limit) 48 if err != nil { 49 if err == db.ErrNoEntries { 50 return util.EmptyPageableResponse(), nil 51 } 52 return nil, gtserror.NewErrorInternalError(err) 53 } 54 55 count := len(reports) 56 items := make([]interface{}, 0, count) 57 nextMaxIDValue := "" 58 prevMinIDValue := "" 59 for i, r := range reports { 60 item, err := p.tc.ReportToAdminAPIReport(ctx, r, account) 61 if err != nil { 62 return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting report to api: %s", err)) 63 } 64 65 if i == count-1 { 66 nextMaxIDValue = item.ID 67 } 68 69 if i == 0 { 70 prevMinIDValue = item.ID 71 } 72 73 items = append(items, item) 74 } 75 76 extraQueryParams := []string{} 77 if resolved != nil { 78 extraQueryParams = append(extraQueryParams, "resolved="+strconv.FormatBool(*resolved)) 79 } 80 if accountID != "" { 81 extraQueryParams = append(extraQueryParams, "account_id="+accountID) 82 } 83 if targetAccountID != "" { 84 extraQueryParams = append(extraQueryParams, "target_account_id="+targetAccountID) 85 } 86 87 return util.PackagePageableResponse(util.PageableResponseParams{ 88 Items: items, 89 Path: "/api/v1/admin/reports", 90 NextMaxIDValue: nextMaxIDValue, 91 PrevMinIDValue: prevMinIDValue, 92 Limit: limit, 93 ExtraQueryParams: extraQueryParams, 94 }) 95 } 96 97 // ReportGet returns one report, with the given ID. 98 func (p *Processor) ReportGet(ctx context.Context, account *gtsmodel.Account, id string) (*apimodel.AdminReport, gtserror.WithCode) { 99 report, err := p.state.DB.GetReportByID(ctx, id) 100 if err != nil { 101 if err == db.ErrNoEntries { 102 return nil, gtserror.NewErrorNotFound(err) 103 } 104 return nil, gtserror.NewErrorInternalError(err) 105 } 106 107 apimodelReport, err := p.tc.ReportToAdminAPIReport(ctx, report, account) 108 if err != nil { 109 return nil, gtserror.NewErrorInternalError(err) 110 } 111 112 return apimodelReport, nil 113 } 114 115 // ReportResolve marks a report with the given id as resolved, 116 // and stores the provided actionTakenComment (if not null). 117 // If the report creator is from this instance, an email will 118 // be sent to them to let them know that the report is resolved. 119 func (p *Processor) ReportResolve(ctx context.Context, account *gtsmodel.Account, id string, actionTakenComment *string) (*apimodel.AdminReport, gtserror.WithCode) { 120 report, err := p.state.DB.GetReportByID(ctx, id) 121 if err != nil { 122 if err == db.ErrNoEntries { 123 return nil, gtserror.NewErrorNotFound(err) 124 } 125 return nil, gtserror.NewErrorInternalError(err) 126 } 127 128 columns := []string{ 129 "action_taken_at", 130 "action_taken_by_account_id", 131 } 132 133 report.ActionTakenAt = time.Now() 134 report.ActionTakenByAccountID = account.ID 135 136 if actionTakenComment != nil { 137 report.ActionTaken = *actionTakenComment 138 columns = append(columns, "action_taken") 139 } 140 141 updatedReport, err := p.state.DB.UpdateReport(ctx, report, columns...) 142 if err != nil { 143 return nil, gtserror.NewErrorInternalError(err) 144 } 145 146 // Process side effects of closing the report. 147 p.state.Workers.EnqueueClientAPI(ctx, messages.FromClientAPI{ 148 APObjectType: ap.ActivityFlag, 149 APActivityType: ap.ActivityUpdate, 150 GTSModel: report, 151 OriginAccount: account, 152 TargetAccount: report.Account, 153 }) 154 155 apimodelReport, err := p.tc.ReportToAdminAPIReport(ctx, updatedReport, account) 156 if err != nil { 157 return nil, gtserror.NewErrorInternalError(err) 158 } 159 160 return apimodelReport, nil 161 }