| 
									
										
										
										
											2023-03-12 16:00:57 +01:00
										 |  |  | // GoToSocial | 
					
						
							|  |  |  | // Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | // SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | // GNU Affero General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | package dereferencing | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 	"errors" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-26 15:34:10 +02:00
										 |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/db" | 
					
						
							|  |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/gtserror" | 
					
						
							|  |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/gtsmodel" | 
					
						
							|  |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/id" | 
					
						
							|  |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/util" | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | // EnrichAnnounce enriches the given boost wrapper status | 
					
						
							|  |  |  | // by either fetching from the DB or dereferencing the target | 
					
						
							|  |  |  | // status, populating the boost wrapper's fields based on the | 
					
						
							|  |  |  | // target status, and then storing the wrapper in the database. | 
					
						
							|  |  |  | // The wrapper is then returned to the caller. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The provided boost wrapper status must have BoostOfURI set. | 
					
						
							|  |  |  | func (d *Dereferencer) EnrichAnnounce( | 
					
						
							|  |  |  | 	ctx context.Context, | 
					
						
							|  |  |  | 	boost *gtsmodel.Status, | 
					
						
							|  |  |  | 	requestUser string, | 
					
						
							|  |  |  | ) (*gtsmodel.Status, error) { | 
					
						
							|  |  |  | 	targetURI := boost.BoostOfURI | 
					
						
							|  |  |  | 	if targetURI == "" { | 
					
						
							|  |  |  | 		// We can't do anything. | 
					
						
							|  |  |  | 		return nil, gtserror.Newf("no URI to dereference") | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 	// Parse the boost target status URI. | 
					
						
							|  |  |  | 	targetURIObj, err := url.Parse(targetURI) | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 		return nil, gtserror.Newf( | 
					
						
							|  |  |  | 			"couldn't parse boost target status URI %s: %w", | 
					
						
							|  |  |  | 			targetURI, err, | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-10 18:42:41 +00:00
										 |  |  | 	// Fetch and dereference status being boosted, noting that | 
					
						
							|  |  |  | 	// d.GetStatusByURI handles domain blocks and local statuses. | 
					
						
							|  |  |  | 	target, _, err := d.GetStatusByURI(ctx, requestUser, targetURIObj) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, gtserror.Newf("error fetching boost target %s: %w", targetURI, err) | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-10 18:42:41 +00:00
										 |  |  | 	if target.BoostOfID != "" { | 
					
						
							|  |  |  | 		// Ensure that the target is not a boost (should not be possible). | 
					
						
							|  |  |  | 		err := gtserror.Newf("target status %s is a boost", targetURI) | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-25 12:09:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-23 15:24:40 +00:00
										 |  |  | 	// Set boost_of_uri again in case the | 
					
						
							|  |  |  | 	// original URI was an indirect link. | 
					
						
							|  |  |  | 	boost.BoostOfURI = target.URI | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 12:51:57 -07:00
										 |  |  | 	// Boosts are not considered sensitive even if their target is. | 
					
						
							|  |  |  | 	boost.Sensitive = util.Ptr(false) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 	// Populate remaining fields on | 
					
						
							|  |  |  | 	// the boost wrapper using target. | 
					
						
							|  |  |  | 	boost.ActivityStreamsType = target.ActivityStreamsType | 
					
						
							|  |  |  | 	boost.BoostOfID = target.ID | 
					
						
							|  |  |  | 	boost.BoostOf = target | 
					
						
							|  |  |  | 	boost.BoostOfAccountID = target.AccountID | 
					
						
							|  |  |  | 	boost.BoostOfAccount = target.Account | 
					
						
							|  |  |  | 	boost.Visibility = target.Visibility | 
					
						
							|  |  |  | 	boost.Federated = target.Federated | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-24 13:27:42 +02:00
										 |  |  | 	// Ensure this Announce is permitted by the Announcee. | 
					
						
							| 
									
										
										
										
											2024-12-05 13:35:07 +00:00
										 |  |  | 	permit, err := d.isPermittedStatus(ctx, requestUser, nil, boost, true) | 
					
						
							| 
									
										
										
										
											2024-07-24 13:27:42 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, gtserror.Newf("error checking permitted status %s: %w", boost.URI, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !permit { | 
					
						
							|  |  |  | 		// Return a checkable error type that can be ignored. | 
					
						
							|  |  |  | 		err := gtserror.Newf("dropping unpermitted status: %s", boost.URI) | 
					
						
							|  |  |  | 		return nil, gtserror.SetNotPermitted(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Generate an ID for the boost wrapper status. | 
					
						
							| 
									
										
										
										
											2024-12-05 13:35:07 +00:00
										 |  |  | 	boost.ID = id.NewULIDFromTime(boost.CreatedAt) | 
					
						
							| 
									
										
										
										
											2024-07-24 13:27:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-26 15:33:42 +02:00
										 |  |  | 	// Store the remote boost wrapper status in database. | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 	switch err = d.state.DB.PutStatus(ctx, boost); { | 
					
						
							|  |  |  | 	case err == nil: | 
					
						
							| 
									
										
										
										
											2024-02-23 15:24:40 +00:00
										 |  |  | 		// all groovy. | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case errors.Is(err, db.ErrAlreadyExists): | 
					
						
							| 
									
										
										
										
											2024-01-19 12:57:29 +00:00
										 |  |  | 		uri := boost.URI | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 		// DATA RACE! We likely lost out to another goroutine | 
					
						
							|  |  |  | 		// in a call to db.Put(Status). Look again in DB by URI. | 
					
						
							| 
									
										
										
										
											2024-01-19 12:57:29 +00:00
										 |  |  | 		boost, err = d.state.DB.GetStatusByURI(ctx, uri) | 
					
						
							| 
									
										
										
										
											2022-09-25 12:09:41 +01:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2024-01-19 12:57:29 +00:00
										 |  |  | 			return nil, gtserror.Newf( | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 				"error getting boost wrapper status %s from database after race: %w", | 
					
						
							| 
									
										
										
										
											2024-01-19 12:57:29 +00:00
										 |  |  | 				uri, err, | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 			) | 
					
						
							| 
									
										
										
										
											2022-09-25 12:09:41 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-23 15:24:40 +00:00
										 |  |  | 	default: // Proper database error. | 
					
						
							| 
									
										
										
										
											2024-01-19 12:57:29 +00:00
										 |  |  | 		return nil, gtserror.Newf("db error inserting status: %w", err) | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 15:27:15 +01:00
										 |  |  | 	return boost, err | 
					
						
							| 
									
										
										
										
											2021-08-10 13:32:39 +02:00
										 |  |  | } |