package saltyim import ( "encoding/json" "fmt" "io" "net/http" "os" "go.mills.io/salty" ) // RegisterRequest is the request used by clients to register to a broker type RegisterRequest struct { Hash string Key string } // NewRegisterRequest reads the signed request body from a client, verifies its signature // and returns the resulting `RegisterRequest` and key used to sign the request on success // otherwise an empty object and en error on failure. func NewRegisterRequest(r io.Reader) (req RegisterRequest, signer string, err error) { body, err := io.ReadAll(r) if err != nil { return } out, key, err := salty.Verify(body) if err != nil { return } signer = key.ID().String() err = json.Unmarshal(out, &req) return } // SendRequest is the request used by clients to send messages via a broker type SendRequest struct { Endpoint string Message string Capabilities Capabilities } // NewSendRequest reads the signed request body from a client, verifies its signature // and returns the resulting `SendRequest` and key used to sign the request on success // otherwise an empty object and en error on failure. func NewSendRequest(r io.Reader) (req SendRequest, signer string, err error) { body, err := io.ReadAll(r) if err != nil { return } out, key, err := salty.Verify(body) if err != nil { return } signer = key.ID().String() err = json.Unmarshal(out, &req) return } // AvatarRequest is the request used by clients to update avatars stored on a broker's avatar service. type AvatarRequest struct { Addr Addr Content []byte } // NewAvatarRequest reads the signed request body from a client, verifies its signature // and returns the resulting `AvatarRequest` and key used to sign the request on success // otherwise an empty object and en error on failure. func NewAvatarRequest(r io.Reader) (req AvatarRequest, signer string, err error) { body, err := io.ReadAll(r) if err != nil { return } out, key, err := salty.Verify(body) if err != nil { return } signer = key.ID().String() err = json.Unmarshal(out, &req) return } // Blob defines the type, filename and whether or not a blob is publicly accessible or not. // A Blob also holds zero or more properties as a map of key/value pairs of string interpreted // by the client. type Blob struct { r io.ReadSeekCloser Type string Public bool Filename string Properties map[string]string } // Close closes the blob and the underlying io.ReadSeekCloser func (b *Blob) Close() error { return b.r.Close() } // Read reads data from the blob from the underlying io.ReadSeekCloser func (b *Blob) Read(p []byte) (n int, err error) { return b.r.Read(p) } // SetHeaders sets HTTP headers on the net/http.Request object based on the blob's type, filename // and various other properties (if any). func (b *Blob) SetHeaders(r *http.Request) { // TODO: Implement this... } // OpenBlob opens a blob at the given path and returns a Blob object func OpenBlob(fn string) (*Blob, error) { f, err := os.Open(fn) if err != nil { return nil, fmt.Errorf("error opening blob %s: %w", fn, err) } return &Blob{r: f}, nil } // BlobRequest is the request used by clients to update blob metadata for blobs stored on a broker. type BlobRequest struct { Blob } // NewBlobRequest reads the signed request body from a client, verifies its signature // and returns the resulting `BlobRequest` and key used to sign the request on success // otherwise an empty object and an error on failure. func NewBlobRequest(r io.Reader) (req BlobRequest, signer string, err error) { body, err := io.ReadAll(r) if err != nil { return } out, key, err := salty.Verify(body) if err != nil { return } signer = key.ID().String() err = json.Unmarshal(out, &req) return } // NewRawRequest reads the signed request body from a client, verifies its signature // and returns the resulting `[]byte` slice and key used to sign the request on success // otherwise an empty object and an error on failure. func NewRawRequest(r io.Reader) (out []byte, signer string, err error) { body, err := io.ReadAll(r) if err != nil { return } out, key, err := salty.Verify(body) if err != nil { return } signer = key.ID().String() return }