// 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 . package admin import ( "context" "errors" "fmt" "net/url" apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/id" "github.com/superseriousbusiness/gotosocial/internal/paging" ) // DomainPermissionSubscriptionGet returns one // domain permission subscription with the given id. func (p *Processor) DomainPermissionSubscriptionGet( ctx context.Context, id string, ) (*apimodel.DomainPermissionSubscription, gtserror.WithCode) { permSub, err := p.state.DB.GetDomainPermissionSubscriptionByID(ctx, id) if err != nil && !errors.Is(err, db.ErrNoEntries) { err := gtserror.Newf("db error getting domain permission subscription %s: %w", id, err) return nil, gtserror.NewErrorInternalError(err) } if permSub == nil { err := fmt.Errorf("domain permission subscription %s not found", id) return nil, gtserror.NewErrorNotFound(err, err.Error()) } return p.apiDomainPermSub(ctx, permSub) } // DomainPermissionSubscriptionsGet returns a page of // DomainPermissionSubscriptions with the given parameters. func (p *Processor) DomainPermissionSubscriptionsGet( ctx context.Context, permType gtsmodel.DomainPermissionType, page *paging.Page, ) (*apimodel.PageableResponse, gtserror.WithCode) { permSubs, err := p.state.DB.GetDomainPermissionSubscriptions( ctx, permType, page, ) if err != nil && !errors.Is(err, db.ErrNoEntries) { err := gtserror.Newf("db error: %w", err) return nil, gtserror.NewErrorInternalError(err) } count := len(permSubs) if count == 0 { return paging.EmptyResponse(), nil } // Get the lowest and highest // ID values, used for paging. lo := permSubs[count-1].ID hi := permSubs[0].ID // Convert each perm sub to API model. items := make([]any, len(permSubs)) for i, permSub := range permSubs { apiPermSub, err := p.converter.DomainPermSubToAPIDomainPermSub(ctx, permSub) if err != nil { return nil, gtserror.NewErrorInternalError(err) } items[i] = apiPermSub } // Assemble next/prev page queries. query := make(url.Values, 1) if permType != gtsmodel.DomainPermissionUnknown { query.Set(apiutil.DomainPermissionPermTypeKey, permType.String()) } return paging.PackageResponse(paging.ResponseParams{ Items: items, Path: "/api/v1/admin/domain_permission_subscriptions", Next: page.Next(lo, hi), Prev: page.Prev(lo, hi), Query: query, }), nil } // DomainPermissionSubscriptionsGetByPriority returns all domain permission // subscriptions of the given permission type, in descending priority order. func (p *Processor) DomainPermissionSubscriptionsGetByPriority( ctx context.Context, permType gtsmodel.DomainPermissionType, ) ([]*apimodel.DomainPermissionSubscription, gtserror.WithCode) { permSubs, err := p.state.DB.GetDomainPermissionSubscriptionsByPriority( ctx, permType, ) if err != nil && !errors.Is(err, db.ErrNoEntries) { err := gtserror.Newf("db error: %w", err) return nil, gtserror.NewErrorInternalError(err) } // Convert each perm sub to API model. items := make([]*apimodel.DomainPermissionSubscription, len(permSubs)) for i, permSub := range permSubs { apiPermSub, err := p.converter.DomainPermSubToAPIDomainPermSub(ctx, permSub) if err != nil { return nil, gtserror.NewErrorInternalError(err) } items[i] = apiPermSub } return items, nil } func (p *Processor) DomainPermissionSubscriptionCreate( ctx context.Context, acct *gtsmodel.Account, priority uint8, title string, uri string, contentType gtsmodel.DomainPermSubContentType, permType gtsmodel.DomainPermissionType, asDraft bool, fetchUsername string, fetchPassword string, ) (*apimodel.DomainPermissionSubscription, gtserror.WithCode) { permSub := >smodel.DomainPermissionSubscription{ ID: id.NewULID(), Priority: priority, Title: title, PermissionType: permType, AsDraft: &asDraft, CreatedByAccountID: acct.ID, CreatedByAccount: acct, URI: uri, ContentType: contentType, FetchUsername: fetchUsername, FetchPassword: fetchPassword, } err := p.state.DB.PutDomainPermissionSubscription(ctx, permSub) if err != nil { if errors.Is(err, db.ErrAlreadyExists) { // Unique constraint conflict. const errText = "domain permission subscription with given URI or title already exists" return nil, gtserror.NewErrorConflict(errors.New(errText), errText) } // Real database error. err := gtserror.Newf("db error putting domain permission subscription: %w", err) return nil, gtserror.NewErrorInternalError(err) } return p.apiDomainPermSub(ctx, permSub) } func (p *Processor) DomainPermissionSubscriptionUpdate( ctx context.Context, id string, priority *uint8, title *string, uri *string, contentType *gtsmodel.DomainPermSubContentType, asDraft *bool, adoptOrphans *bool, fetchUsername *string, fetchPassword *string, ) (*apimodel.DomainPermissionSubscription, gtserror.WithCode) { permSub, err := p.state.DB.GetDomainPermissionSubscriptionByID(ctx, id) if err != nil && !errors.Is(err, db.ErrNoEntries) { err := gtserror.Newf("db error getting domain permission subscription %s: %w", id, err) return nil, gtserror.NewErrorInternalError(err) } if permSub == nil { err := fmt.Errorf("domain permission subscription %s not found", id) return nil, gtserror.NewErrorNotFound(err, err.Error()) } columns := make([]string, 0, 7) if priority != nil { permSub.Priority = *priority columns = append(columns, "priority") } if title != nil { permSub.Title = *title columns = append(columns, "title") } if uri != nil { permSub.URI = *uri columns = append(columns, "uri") } if contentType != nil { permSub.ContentType = *contentType columns = append(columns, "content_type") } if asDraft != nil { permSub.AsDraft = asDraft columns = append(columns, "as_draft") } if adoptOrphans != nil { permSub.AdoptOrphans = adoptOrphans columns = append(columns, "adopt_orphans") } if fetchPassword != nil { permSub.FetchPassword = *fetchPassword columns = append(columns, "fetch_password") } if fetchUsername != nil { permSub.FetchUsername = *fetchUsername columns = append(columns, "fetch_username") } err = p.state.DB.UpdateDomainPermissionSubscription(ctx, permSub, columns...) if err != nil { if errors.Is(err, db.ErrAlreadyExists) { // Unique constraint conflict. const errText = "domain permission subscription with given URI or title already exists" return nil, gtserror.NewErrorConflict(errors.New(errText), errText) } // Real database error. err := gtserror.Newf("db error updating domain permission subscription: %w", err) return nil, gtserror.NewErrorInternalError(err) } return p.apiDomainPermSub(ctx, permSub) } func (p *Processor) DomainPermissionSubscriptionRemove( ctx context.Context, id string, removeChildren bool, ) (*apimodel.DomainPermissionSubscription, gtserror.WithCode) { permSub, err := p.state.DB.GetDomainPermissionSubscriptionByID(ctx, id) if err != nil && !errors.Is(err, db.ErrNoEntries) { err := gtserror.Newf("db error getting domain permission subscription %s: %w", id, err) return nil, gtserror.NewErrorInternalError(err) } if permSub == nil { err := fmt.Errorf("domain permission subscription %s not found", id) return nil, gtserror.NewErrorNotFound(err, err.Error()) } // TODO in next PR: if removeChildren, then remove all // domain permissions that are children of this domain // permission subscription. If not removeChildren, then // just unlink them by clearing their subscription ID. // For now just delete the domain permission subscription. if err := p.state.DB.DeleteDomainPermissionSubscription(ctx, id); err != nil { err := gtserror.Newf("db error deleting domain permission subscription: %w", err) return nil, gtserror.NewErrorInternalError(err) } return p.apiDomainPermSub(ctx, permSub) }