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 }