Live video on the AT Protocol
at natb/dropdown-stuff-2 108 lines 3.1 kB view raw
1package api 2 3import ( 4 "context" 5 "crypto" 6 "fmt" 7 8 atcrypto "github.com/bluesky-social/indigo/atproto/crypto" 9 "github.com/decred/dcrd/dcrec/secp256k1" 10 "github.com/mr-tron/base58" 11 "stream.place/streamplace/pkg/atproto" 12 "stream.place/streamplace/pkg/log" 13 "stream.place/streamplace/pkg/media" 14) 15 16func (a *StreamplaceAPI) MakeMediaSigner(ctx context.Context, keyStr string) (media.MediaSigner, error) { 17 if len(keyStr) < 2 || keyStr[0] != 'z' { 18 return nil, fmt.Errorf("invalid authorization key (not a multibase base58btc string)") 19 } 20 21 var addrBytes []byte 22 var didBytes []byte 23 priv, err := atcrypto.ParsePrivateMultibase(keyStr) 24 if err == nil { 25 addrBytes = priv.Bytes() 26 } else { 27 decoded, err := base58.Decode(keyStr[1:]) 28 if err != nil { 29 return nil, fmt.Errorf("invalid authorization key (not a base58btc string)") 30 } 31 addrBytes = decoded[:32] 32 didBytes = decoded[32:] 33 priv, err = atcrypto.ParsePrivateBytesK256(addrBytes) 34 if err != nil { 35 return nil, fmt.Errorf("invalid authorization key (not valid atproto): %w", err) 36 } 37 } 38 39 key, _ := secp256k1.PrivKeyFromBytes(addrBytes) 40 if key == nil { 41 return nil, fmt.Errorf("invalid authorization key (not valid secp256k1)") 42 } 43 var signer crypto.Signer = key.ToECDSA() 44 pub, err := priv.PublicKey() 45 if err != nil { 46 return nil, fmt.Errorf("invalid authorization key (could not parse as atproto): %w", err) 47 } 48 49 did := string(didBytes) 50 51 if did != "" { 52 repo, err := a.ATSync.SyncBlueskyRepo(ctx, did, a.Model) 53 if err != nil { 54 return nil, fmt.Errorf("could not resolve streamplace key: %w", err) 55 } 56 err = a.CLI.StreamIsAllowed(repo.DID) 57 if err != nil { 58 return nil, fmt.Errorf("user is not allowed to stream: %w", err) 59 } 60 signingKey, err := a.Model.GetSigningKey(ctx, pub.DIDKey(), repo.DID) 61 if err != nil { 62 return nil, fmt.Errorf("signing key not found: %w", err) 63 } 64 if signingKey == nil { 65 return nil, fmt.Errorf("signing key not found") 66 } 67 } else { 68 atkey, err := atproto.ParsePubKey(signer.Public()) 69 if err != nil { 70 return nil, fmt.Errorf("invalid authorization key (not valid secp256k1): %w", err) 71 } 72 did = atkey.DIDKey() 73 err = a.CLI.StreamIsAllowed(did) 74 if err != nil { 75 return nil, fmt.Errorf("user is not allowed to stream: %w", err) 76 } 77 } 78 79 ctx = log.WithLogValues(ctx, "did", did) 80 err = a.checkBanned(ctx, did) 81 if err != nil { 82 return nil, err 83 } 84 85 var mediaSigner media.MediaSigner 86 if a.CLI.ExternalSigning { 87 mediaSigner, err = media.MakeMediaSignerExt(ctx, a.CLI, did, addrBytes, a.Model) 88 } else { 89 mediaSigner, err = media.MakeMediaSigner(ctx, a.CLI, did, signer, a.Model) 90 } 91 if err != nil { 92 return nil, fmt.Errorf("invalid authorization key (not valid secp256k1): %w", err) 93 } 94 95 return mediaSigner, nil 96} 97 98func (a *StreamplaceAPI) checkBanned(ctx context.Context, did string) error { 99 labels, err := a.Model.GetActiveLabels(did) 100 if err != nil { 101 return fmt.Errorf("failed to get active labels: %w", err) 102 } 103 if atproto.IsBanned(labels...) { 104 log.Error(ctx, "user is banned", "did", did) 105 return fmt.Errorf("user is banned") 106 } 107 return nil 108}