gtsocial-umbx

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

domain.go (4445B)


      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 bundb
     19 
     20 import (
     21 	"context"
     22 	"net/url"
     23 
     24 	"github.com/superseriousbusiness/gotosocial/internal/config"
     25 	"github.com/superseriousbusiness/gotosocial/internal/db"
     26 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     27 	"github.com/superseriousbusiness/gotosocial/internal/state"
     28 	"github.com/superseriousbusiness/gotosocial/internal/util"
     29 	"github.com/uptrace/bun"
     30 )
     31 
     32 type domainDB struct {
     33 	conn  *DBConn
     34 	state *state.State
     35 }
     36 
     37 func (d *domainDB) CreateDomainBlock(ctx context.Context, block *gtsmodel.DomainBlock) db.Error {
     38 	// Normalize the domain as punycode
     39 	var err error
     40 	block.Domain, err = util.Punify(block.Domain)
     41 	if err != nil {
     42 		return err
     43 	}
     44 
     45 	// Attempt to store domain in DB
     46 	if _, err := d.conn.NewInsert().
     47 		Model(block).
     48 		Exec(ctx); err != nil {
     49 		return d.conn.ProcessError(err)
     50 	}
     51 
     52 	// Clear the domain block cache (for later reload)
     53 	d.state.Caches.GTS.DomainBlock().Clear()
     54 
     55 	return nil
     56 }
     57 
     58 func (d *domainDB) GetDomainBlock(ctx context.Context, domain string) (*gtsmodel.DomainBlock, db.Error) {
     59 	// Normalize the domain as punycode
     60 	domain, err := util.Punify(domain)
     61 	if err != nil {
     62 		return nil, err
     63 	}
     64 
     65 	// Check for easy case, domain referencing *us*
     66 	if domain == "" || domain == config.GetAccountDomain() ||
     67 		domain == config.GetHost() {
     68 		return nil, db.ErrNoEntries
     69 	}
     70 
     71 	var block gtsmodel.DomainBlock
     72 
     73 	// Look for block matching domain in DB
     74 	q := d.conn.
     75 		NewSelect().
     76 		Model(&block).
     77 		Where("? = ?", bun.Ident("domain_block.domain"), domain)
     78 	if err := q.Scan(ctx); err != nil {
     79 		return nil, d.conn.ProcessError(err)
     80 	}
     81 
     82 	return &block, nil
     83 }
     84 
     85 func (d *domainDB) DeleteDomainBlock(ctx context.Context, domain string) db.Error {
     86 	// Normalize the domain as punycode
     87 	domain, err := util.Punify(domain)
     88 	if err != nil {
     89 		return err
     90 	}
     91 
     92 	// Attempt to delete domain block
     93 	if _, err := d.conn.NewDelete().
     94 		Model((*gtsmodel.DomainBlock)(nil)).
     95 		Where("? = ?", bun.Ident("domain_block.domain"), domain).
     96 		Exec(ctx); err != nil {
     97 		return d.conn.ProcessError(err)
     98 	}
     99 
    100 	// Clear the domain block cache (for later reload)
    101 	d.state.Caches.GTS.DomainBlock().Clear()
    102 
    103 	return nil
    104 }
    105 
    106 func (d *domainDB) IsDomainBlocked(ctx context.Context, domain string) (bool, db.Error) {
    107 	// Normalize the domain as punycode
    108 	domain, err := util.Punify(domain)
    109 	if err != nil {
    110 		return false, err
    111 	}
    112 
    113 	// Check for easy case, domain referencing *us*
    114 	if domain == "" || domain == config.GetAccountDomain() ||
    115 		domain == config.GetHost() {
    116 		return false, nil
    117 	}
    118 
    119 	// Check the cache for a domain block (hydrating the cache with callback if necessary)
    120 	return d.state.Caches.GTS.DomainBlock().IsBlocked(domain, func() ([]string, error) {
    121 		var domains []string
    122 
    123 		// Scan list of all blocked domains from DB
    124 		q := d.conn.NewSelect().
    125 			Table("domain_blocks").
    126 			Column("domain")
    127 		if err := q.Scan(ctx, &domains); err != nil {
    128 			return nil, d.conn.ProcessError(err)
    129 		}
    130 
    131 		return domains, nil
    132 	})
    133 }
    134 
    135 func (d *domainDB) AreDomainsBlocked(ctx context.Context, domains []string) (bool, db.Error) {
    136 	for _, domain := range domains {
    137 		if blocked, err := d.IsDomainBlocked(ctx, domain); err != nil {
    138 			return false, err
    139 		} else if blocked {
    140 			return blocked, nil
    141 		}
    142 	}
    143 	return false, nil
    144 }
    145 
    146 func (d *domainDB) IsURIBlocked(ctx context.Context, uri *url.URL) (bool, db.Error) {
    147 	return d.IsDomainBlocked(ctx, uri.Hostname())
    148 }
    149 
    150 func (d *domainDB) AreURIsBlocked(ctx context.Context, uris []*url.URL) (bool, db.Error) {
    151 	for _, uri := range uris {
    152 		if blocked, err := d.IsDomainBlocked(ctx, uri.Hostname()); err != nil {
    153 			return false, err
    154 		} else if blocked {
    155 			return blocked, nil
    156 		}
    157 	}
    158 	return false, nil
    159 }