gtsocial-umbx

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

instancepeersget.go (5533B)


      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 instance
     19 
     20 import (
     21 	"fmt"
     22 	"net/http"
     23 	"strings"
     24 
     25 	apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
     26 	"github.com/superseriousbusiness/gotosocial/internal/config"
     27 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     28 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     29 
     30 	"github.com/gin-gonic/gin"
     31 )
     32 
     33 // InstancePeersGETHandler swagger:operation GET /api/v1/instance/peers instancePeersGet
     34 //
     35 //	---
     36 //	tags:
     37 //	- instance
     38 //
     39 //	produces:
     40 //	- application/json
     41 //
     42 //	parameters:
     43 //	-
     44 //		name: filter
     45 //		type: string
     46 //		description: |-
     47 //			Comma-separated list of filters to apply to results. Recognized filters are:
     48 //				- `open` -- include peers that are not suspended or silenced
     49 //				- `suspended` -- include peers that have been suspended.
     50 //
     51 //			If filter is `open`, only instances that haven't been suspended or silenced will be returned.
     52 //
     53 //			If filter is `suspended`, only suspended instances will be shown.
     54 //
     55 //			If filter is `open,suspended`, then all known instances will be returned.
     56 //
     57 //			If filter is an empty string or not set, then `open` will be assumed as the default.
     58 //		in: query
     59 //		required: false
     60 //		default: "open"
     61 //
     62 //	responses:
     63 //		'200':
     64 //			description: >-
     65 //				If no filter parameter is provided, or filter is empty, then a legacy,
     66 //				Mastodon-API compatible response will be returned. This will consist of
     67 //				just a 'flat' array of strings like `["example.com", "example.org"]`,
     68 //				which corresponds to domains this instance peers with.
     69 //
     70 //
     71 //				If a filter parameter is provided, then an array of objects with at least
     72 //				a `domain` key set on each object will be returned.
     73 //
     74 //
     75 //				Domains that are silenced or suspended will also have a key
     76 //				`suspended_at` or `silenced_at` that contains an iso8601 date string.
     77 //				If one of these keys is not present on the domain object, it is open.
     78 //				Suspended instances may in some cases be obfuscated, which means they
     79 //				will have some letters replaced by `*` to make it more difficult for
     80 //				bad actors to target instances with harassment.
     81 //
     82 //
     83 //				Whether a flat response or a more detailed response is returned, domains
     84 //				will be sorted alphabetically by hostname.
     85 //			schema:
     86 //				type: array
     87 //				items:
     88 //					"$ref": "#/definitions/domain"
     89 //		'400':
     90 //			description: bad request
     91 //		'401':
     92 //			description: unauthorized
     93 //		'403':
     94 //			description: forbidden
     95 //		'404':
     96 //			description: not found
     97 //		'406':
     98 //			description: not acceptable
     99 //		'500':
    100 //			description: internal server error
    101 func (m *Module) InstancePeersGETHandler(c *gin.Context) {
    102 	authed, err := oauth.Authed(c, false, false, false, false)
    103 	if err != nil {
    104 		apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1)
    105 		return
    106 	}
    107 
    108 	isUnauthenticated := authed.Account == nil || authed.User == nil
    109 
    110 	if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
    111 		apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
    112 		return
    113 	}
    114 
    115 	var includeSuspended bool
    116 	var includeOpen bool
    117 	var flat bool
    118 	if filterParam := c.Query(PeersFilterKey); filterParam != "" {
    119 		filters := strings.Split(filterParam, ",")
    120 		for _, f := range filters {
    121 			trimmed := strings.TrimSpace(f)
    122 			switch {
    123 			case strings.EqualFold(trimmed, "suspended"):
    124 				includeSuspended = true
    125 			case strings.EqualFold(trimmed, "open"):
    126 				includeOpen = true
    127 			default:
    128 				err := fmt.Errorf("filter %s not recognized; accepted values are 'open', 'suspended'", trimmed)
    129 				apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1)
    130 				return
    131 			}
    132 		}
    133 	} else {
    134 		// default is to only include open domains, and present
    135 		// them in a 'flat' manner (just an array of strings),
    136 		// to maintain compatibility with mastodon API
    137 		includeOpen = true
    138 		flat = true
    139 	}
    140 
    141 	if includeOpen && !config.GetInstanceExposePeers() && isUnauthenticated {
    142 		err := fmt.Errorf("peers open query requires an authenticated account/user")
    143 		apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1)
    144 		return
    145 	}
    146 
    147 	if includeSuspended && !config.GetInstanceExposeSuspended() && isUnauthenticated {
    148 		err := fmt.Errorf("peers suspended query requires an authenticated account/user")
    149 		apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1)
    150 		return
    151 	}
    152 
    153 	data, errWithCode := m.processor.InstancePeersGet(c.Request.Context(), includeSuspended, includeOpen, flat)
    154 	if errWithCode != nil {
    155 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    156 		return
    157 	}
    158 
    159 	c.JSON(http.StatusOK, data)
    160 }