2022-03-22 22:59:09 +00:00
|
|
|
package saltyim
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2023-01-25 23:05:29 +00:00
|
|
|
"fmt"
|
2022-03-22 22:59:09 +00:00
|
|
|
"io"
|
2023-01-25 23:05:29 +00:00
|
|
|
"net/http"
|
|
|
|
"os"
|
2022-03-22 22:59:09 +00:00
|
|
|
|
|
|
|
"go.mills.io/salty"
|
|
|
|
)
|
|
|
|
|
|
|
|
// RegisterRequest is the request used by clients to register to a broker
|
|
|
|
type RegisterRequest struct {
|
2022-04-04 16:04:38 +00:00
|
|
|
Hash string
|
2022-03-22 22:59:09 +00:00
|
|
|
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) {
|
2023-01-11 22:58:07 +00:00
|
|
|
body, err := io.ReadAll(r)
|
2022-03-22 22:59:09 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
out, key, err := salty.Verify(body)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
signer = key.ID().String()
|
|
|
|
err = json.Unmarshal(out, &req)
|
|
|
|
return
|
|
|
|
}
|
2022-03-31 03:46:12 +00:00
|
|
|
|
|
|
|
// 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) {
|
2023-01-11 22:58:07 +00:00
|
|
|
body, err := io.ReadAll(r)
|
2022-03-31 03:46:12 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
out, key, err := salty.Verify(body)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
signer = key.ID().String()
|
|
|
|
err = json.Unmarshal(out, &req)
|
|
|
|
return
|
|
|
|
}
|
2022-04-02 02:59:39 +00:00
|
|
|
|
2023-01-25 23:05:29 +00:00
|
|
|
// AvatarRequest is the request used by clients to update avatars stored on a broker's avatar service.
|
2022-04-02 02:59:39 +00:00
|
|
|
type AvatarRequest struct {
|
2023-01-26 22:30:16 +00:00
|
|
|
Addr Addr
|
2022-04-02 02:59:39 +00:00
|
|
|
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) {
|
2023-01-11 22:58:07 +00:00
|
|
|
body, err := io.ReadAll(r)
|
2022-04-02 02:59:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
out, key, err := salty.Verify(body)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
signer = key.ID().String()
|
|
|
|
err = json.Unmarshal(out, &req)
|
|
|
|
return
|
|
|
|
}
|
2023-01-25 23:05:29 +00:00
|
|
|
|
|
|
|
// Blob defines the type, filename and whether or not a blob is publicly accessible or not.
|
2023-01-27 23:24:19 +00:00
|
|
|
// A Blob also holds zero or more properties as a map of key/value pairs of string interpreted
|
2023-01-25 23:05:29 +00:00
|
|
|
// 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
|
2023-01-27 23:24:19 +00:00
|
|
|
// otherwise an empty object and an error on failure.
|
2023-01-25 23:05:29 +00:00
|
|
|
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
|
2023-01-27 23:24:19 +00:00
|
|
|
// otherwise an empty object and an error on failure.
|
2023-01-25 23:05:29 +00:00
|
|
|
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
|
|
|
|
}
|