···2233import (
44 "context"
55- "database/sql"
65 "errors"
76 "fmt"
87 "log/slog"
···1312 "sync"
1413 "time"
15141616- "github.com/bluesky-social/indigo/api/atproto"
1715 "github.com/bluesky-social/indigo/bgs"
1816 "github.com/bluesky-social/indigo/carstore"
1917 "github.com/bluesky-social/indigo/did"
2018 "github.com/bluesky-social/indigo/events"
2121- "github.com/bluesky-social/indigo/handles"
2219 "github.com/bluesky-social/indigo/models"
2320 "github.com/bluesky-social/indigo/repomgr"
2421 "github.com/bluesky-social/indigo/util/svcutil"
···4138 db *gorm.DB
4239 slurper *bgs.Slurper
4340 didr did.Resolver
4444-4545- hr handles.HandleResolver
46414742 // TODO: work on doing away with this flag in favor of more pluggable
4843 // pieces that abstract the need for explicit ssl checks
···10196 }
10297}
10398104104-func NewArchiver(db *gorm.DB, ix *Indexer, repoman *repomgr.RepoManager, didr did.Resolver, rf *RepoFetcher, hr handles.HandleResolver, config *ArchiverConfig) (*Archiver, error) {
9999+func NewArchiver(db *gorm.DB, ix *Indexer, repoman *repomgr.RepoManager, didr did.Resolver, rf *RepoFetcher, config *ArchiverConfig) (*Archiver, error) {
105100 if config == nil {
106101 config = DefaultArchiverConfig()
107102 }
···116111 Index: ix,
117112 db: db,
118113119119- hr: hr,
120114 repoman: repoman,
121115 didr: didr,
122116 ssl: config.SSL,
···165159166160type User struct {
167161 gorm.Model
168168- ID models.Uid `gorm:"primarykey;index:idx_user_id_active,where:taken_down = false AND tombstoned = false"`
169169- Handle sql.NullString `gorm:"index"`
170170- DisplayName string
171171- Did string `gorm:"uniqueindex"`
172172- Following int64
173173- Followers int64
174174- Posts int64
175175- Type string
176176- PDS uint
177177- ValidHandle bool `gorm:"default:true"`
162162+ ID models.Uid `gorm:"primarykey;index:idx_user_id_active,where:taken_down = false AND tombstoned = false"`
163163+ Did string `gorm:"uniqueindex"`
164164+ PDS uint
178165179166 // TakenDown is set to true if the user in question has been taken down.
180167 // A user in this state will have all future events related to it dropped
···257244 return nil, err
258245 }
259246260260- /*
261261- // TODO: ignore this because we're just gonna get the stream from the relay anyways
262262- ban, err := s.domainIsBanned(ctx, durl.Host)
263263- if err != nil {
264264- return nil, fmt.Errorf("failed to check pds ban status: %w", err)
265265- }
266266-267267- if ban {
268268- return nil, fmt.Errorf("cannot create user on pds with banned domain")
269269- }
270270- */
271271-272247 c := &xrpc.Client{Host: durl.String()}
273248 s.Index.ApplyPDSClientSettings(c)
274249275250 if peering.ID == 0 {
276276- // TODO: the case of handling a new user on a new PDS probably requires more thought
277277- cfg, err := atproto.ServerDescribeServer(ctx, c)
278278- if err != nil {
279279- // TODO: failing this shouldn't halt our indexing
280280- return nil, fmt.Errorf("failed to check unrecognized pds: %w", err)
281281- }
282282-283283- // since handles can be anything, checking against this list doesn't matter...
284284- _ = cfg
285285-286286- // TODO: could check other things, a valid response is good enough for now
287251 peering.Host = durl.Host
288252 peering.SSL = (durl.Scheme == "https")
289253 peering.CrawlRateLimit = float64(s.slurper.DefaultCrawlLimit)
···338302 return nil, fmt.Errorf("user has no 'known as' field in their DID document")
339303 }
340304341341- hurl, err := url.Parse(doc.AlsoKnownAs[0])
342342- if err != nil {
343343- return nil, err
344344- }
345345-346346- s.log.Debug("creating external user", "did", did, "handle", hurl.Host, "pds", peering.ID)
347347-348348- handle := hurl.Host
349349-350350- validHandle := true
351351-352352- resdid, err := s.hr.ResolveHandleToDid(ctx, handle)
353353- if err != nil {
354354- s.log.Error("failed to resolve users claimed handle on pds", "handle", handle, "err", err)
355355- validHandle = false
356356- }
357357-358358- if resdid != did {
359359- s.log.Error("claimed handle did not match servers response", "resdid", resdid, "did", did)
360360- validHandle = false
361361- }
305305+ s.log.Debug("creating external user", "did", did, "pds", peering.ID)
362306363307 s.extUserLk.Lock()
364308 defer s.extUserLk.Unlock()
365309366310 exu, err := s.Index.LookupUserByDid(ctx, did)
367311 if err == nil {
368368- s.log.Debug("lost the race to create a new user", "did", did, "handle", handle, "existing_hand", exu.Handle)
312312+ s.log.Debug("lost the race to create a new user", "did", did)
369313 if exu.PDS != peering.ID {
370314 // User is now on a different PDS, update
371315 if err := s.db.Model(User{}).Where("id = ?", exu.ID).Update("pds", peering.ID).Error; err != nil {
···375319 exu.PDS = peering.ID
376320 }
377321378378- if exu.Handle.String != handle {
379379- // Users handle has changed, update
380380- if err := s.db.Model(User{}).Where("id = ?", exu.ID).Update("handle", handle).Error; err != nil {
381381- return nil, fmt.Errorf("failed to update users handle: %w", err)
382382- }
383383-384384- exu.Handle = sql.NullString{String: handle, Valid: true}
385385- }
386322 return exu, nil
387323 }
388324···390326 return nil, err
391327 }
392328393393- // TODO: request this users info from their server to fill out our data...
394329 u := User{
395395- Did: did,
396396- PDS: peering.ID,
397397- ValidHandle: validHandle,
398398- }
399399- if validHandle {
400400- u.Handle = sql.NullString{String: handle, Valid: true}
330330+ Did: did,
331331+ PDS: peering.ID,
401332 }
402333403334 if err := s.db.Create(&u).Error; err != nil {
404404- // If the new user's handle conflicts with an existing user,
405405- // since we just validated the handle for this user, we'll assume
406406- // the existing user no longer has control of the handle
407407- if errors.Is(err, gorm.ErrDuplicatedKey) {
408408- // Get the UID of the existing user
409409- var existingUser User
410410- if err := s.db.Find(&existingUser, "handle = ?", handle).Error; err != nil {
411411- return nil, fmt.Errorf("failed to find existing user: %w", err)
412412- }
413413-414414- // Set the existing user's handle to NULL and set the valid_handle flag to false
415415- if err := s.db.Model(User{}).Where("id = ?", existingUser.ID).Update("handle", nil).Update("valid_handle", false).Error; err != nil {
416416- return nil, fmt.Errorf("failed to update outdated user's handle: %w", err)
417417- }
418418-419419- // Create the new user
420420- if err := s.db.Create(&u).Error; err != nil {
421421- return nil, fmt.Errorf("failed to create user after handle conflict: %w", err)
422422- }
423423-424424- s.userCache.Remove(did)
425425- } else {
426426- return nil, fmt.Errorf("failed to create other pds user: %w", err)
427427- }
335335+ return nil, fmt.Errorf("failed to create other pds user: %w", err)
428336 }
429337430338 successfullyCreated = true