Files
bridge/internal/permissions/relationships.go

113 lines
3.1 KiB
Go

package permissions
import (
"context"
"fmt"
"net/http"
"go.infratographer.com/x/gidx"
)
type resourceRelationship struct {
ResourceID string `json:"resource_id"`
Relation string `json:"relation"`
SubjectID string `json:"subject_id"`
}
// ResourceRelationship defines the resource to subject relationship.
type ResourceRelationship struct {
ResourceID gidx.PrefixedID
Relation string
SubjectID gidx.PrefixedID
}
// ResourceRelationshipRequest defines the request to relate to a subject.
type ResourceRelationshipRequest struct {
Relation string `json:"relation"`
SubjectID string `json:"subject_id"`
}
// ResourceRelationshipDeleteResponse defines the response for a delete of a relationship.
type ResourceRelationshipDeleteResponse struct {
Success bool `json:"success"`
}
// DeleteResourceRelationship deletes the provided resources relationship to the given subject id.
func (c *client) DeleteResourceRelationship(ctx context.Context, resourceID gidx.PrefixedID, relation string, relatedResourceID gidx.PrefixedID) error {
path := fmt.Sprintf("/api/v1/resources/%s/relationships", resourceID.String())
body, err := encodeJSON(ResourceRelationshipRequest{
Relation: relation,
SubjectID: relatedResourceID.String(),
})
if err != nil {
return err
}
var response ResourceRelationshipDeleteResponse
if _, err := c.DoRequest(ctx, http.MethodDelete, path, body, &response); err != nil { // nolint:bodyclose // closed by Do on json decode.
return err
}
if !response.Success {
return ErrUnexpectedRelationshipDeleteFailed
}
return nil
}
// ListResourceRelationshipsFrom returns resources related to the given id.
func (c *client) ListResourceRelationshipsFrom(ctx context.Context, resourceID gidx.PrefixedID) ([]ResourceRelationship, error) {
var response struct {
Data []resourceRelationship `json:"data"`
}
if _, err := c.DoRequest(ctx, http.MethodGet, fmt.Sprintf("/api/v1/relationships/from/%s", resourceID.String()), nil, &response); err != nil { // nolint:bodyclose // closed by Do on json decode.
return nil, err
}
data := make([]ResourceRelationship, len(response.Data))
for i, entry := range response.Data {
subID, err := gidx.Parse(entry.SubjectID)
if err != nil {
return nil, err
}
data[i] = ResourceRelationship{
Relation: entry.Relation,
SubjectID: subID,
}
}
return data, nil
}
// ListResourceRelationshipsTo returns resources related to the given id.
func (c *client) ListResourceRelationshipsTo(ctx context.Context, resourceID gidx.PrefixedID) ([]ResourceRelationship, error) {
var response struct {
Data []resourceRelationship `json:"data"`
}
if _, err := c.DoRequest(ctx, http.MethodGet, fmt.Sprintf("/api/v1/relationships/to/%s", resourceID.String()), nil, &response); err != nil { // nolint:bodyclose // closed by Do on json decode.
return nil, err
}
data := make([]ResourceRelationship, len(response.Data))
for i, entry := range response.Data {
resID, err := gidx.Parse(entry.ResourceID)
if err != nil {
return nil, err
}
data[i] = ResourceRelationship{
ResourceID: resID,
Relation: entry.Relation,
}
}
return data, nil
}