-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add create/delete of auth relationships to permissions package
Signed-off-by: Mike Mason <[email protected]>
- Loading branch information
Showing
7 changed files
with
542 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Package mockpermissions implements permissions.AuthRelationshipRequestHandler. | ||
// Simplifying testing of relationship creation in applications. | ||
package mockpermissions | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/stretchr/testify/mock" | ||
"go.infratographer.com/permissions-api/pkg/permissions" | ||
"go.infratographer.com/x/events" | ||
"go.infratographer.com/x/gidx" | ||
) | ||
|
||
var _ permissions.AuthRelationshipRequestHandler = (*MockPermissions)(nil) | ||
|
||
// MockPermissions implements permissions.AuthRelationshipRequestHandler. | ||
type MockPermissions struct { | ||
mock.Mock | ||
} | ||
|
||
// ContextWithHandler returns the context with the mock permissions handler defined. | ||
func (p *MockPermissions) ContextWithHandler(ctx context.Context) context.Context { | ||
return context.WithValue(ctx, permissions.AuthRelationshipRequestHandlerCtxKey, p) | ||
} | ||
|
||
// CreateAuthRelationships implements permissions.AuthRelationshipRequestHandler. | ||
func (p *MockPermissions) CreateAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error { | ||
calledArgs := []interface{}{topic, resourceID} | ||
|
||
for _, rel := range relations { | ||
calledArgs = append(calledArgs, rel) | ||
} | ||
|
||
args := p.Called(calledArgs...) | ||
|
||
return args.Error(0) | ||
} | ||
|
||
// DeleteAuthRelationships implements permissions.AuthRelationshipRequestHandler. | ||
func (p *MockPermissions) DeleteAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error { | ||
calledArgs := []interface{}{topic, resourceID} | ||
|
||
for _, rel := range relations { | ||
calledArgs = append(calledArgs, rel) | ||
} | ||
|
||
args := p.Called(calledArgs...) | ||
|
||
return args.Error(0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package mockpermissions_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
"go.infratographer.com/permissions-api/pkg/permissions" | ||
"go.infratographer.com/permissions-api/pkg/permissions/mockpermissions" | ||
"go.infratographer.com/x/events" | ||
"go.infratographer.com/x/gidx" | ||
) | ||
|
||
func TestPermissions(t *testing.T) { | ||
t.Run("create", func(t *testing.T) { | ||
mockPerms := new(mockpermissions.MockPermissions) | ||
|
||
ctx := mockPerms.ContextWithHandler(context.Background()) | ||
|
||
relation := events.AuthRelationshipRelation{ | ||
Relation: "parent", | ||
SubjectID: "tnntten-abc", | ||
} | ||
|
||
mockPerms.On("CreateAuthRelationships", "test", gidx.PrefixedID("tnntten-abc123"), relation).Return(nil) | ||
|
||
err := permissions.CreateAuthRelationships(ctx, "test", "tnntten-abc123", relation) | ||
require.NoError(t, err) | ||
|
||
mockPerms.AssertExpectations(t) | ||
}) | ||
t.Run("delete", func(t *testing.T) { | ||
mockPerms := new(mockpermissions.MockPermissions) | ||
|
||
ctx := mockPerms.ContextWithHandler(context.Background()) | ||
|
||
relation := events.AuthRelationshipRelation{ | ||
Relation: "parent", | ||
SubjectID: "tnntten-abc", | ||
} | ||
|
||
mockPerms.On("DeleteAuthRelationships", "test", gidx.PrefixedID("tnntten-abc123"), relation).Return(nil) | ||
|
||
err := permissions.DeleteAuthRelationships(ctx, "test", "tnntten-abc123", relation) | ||
require.NoError(t, err) | ||
|
||
mockPerms.AssertExpectations(t) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package permissions | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
"github.com/labstack/echo/v4" | ||
"go.infratographer.com/x/events" | ||
"go.infratographer.com/x/gidx" | ||
"go.opentelemetry.io/otel/attribute" | ||
"go.opentelemetry.io/otel/codes" | ||
"go.opentelemetry.io/otel/trace" | ||
"go.uber.org/multierr" | ||
) | ||
|
||
var ( | ||
// AuthRelationshipRequestHandlerCtxKey is the context key used to set the auth relationship request handler. | ||
AuthRelationshipRequestHandlerCtxKey = authRelationshipRequestHandlerCtxKey{} | ||
) | ||
|
||
type authRelationshipRequestHandlerCtxKey struct{} | ||
|
||
func setAuthRelationshipRequestHandler(c echo.Context, requestHandler AuthRelationshipRequestHandler) { | ||
|
||
req := c.Request().WithContext( | ||
context.WithValue( | ||
c.Request().Context(), | ||
AuthRelationshipRequestHandlerCtxKey, | ||
requestHandler, | ||
), | ||
) | ||
|
||
c.SetRequest(req) | ||
} | ||
|
||
// AuthRelationshipRequestHandler defines the required methods to create or update an auth relationship. | ||
type AuthRelationshipRequestHandler interface { | ||
CreateAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error | ||
DeleteAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error | ||
} | ||
|
||
func (p *Permissions) submitAuthRelationshipRequest(ctx context.Context, topic string, request events.AuthRelationshipRequest) error { | ||
ctx, span := tracer.Start(ctx, "permissions.submitAuthRelationshipRequest", | ||
trace.WithAttributes( | ||
attribute.String("events.topic", topic), | ||
attribute.String("events.object_id", request.ObjectID.String()), | ||
attribute.String("events.action", string(request.Action)), | ||
), | ||
) | ||
|
||
defer span.End() | ||
|
||
if err := request.Validate(); err != nil { | ||
span.RecordError(err) | ||
span.SetStatus(codes.Error, err.Error()) | ||
|
||
return err | ||
} | ||
|
||
// if no publisher is defined, requests are disabled. | ||
if p.publisher == nil { | ||
span.AddEvent("publish requests disabled") | ||
|
||
return nil | ||
} | ||
|
||
var errs []error | ||
|
||
resp, err := p.publisher.PublishAuthRelationshipRequest(ctx, topic, request) | ||
if err != nil { | ||
if p.ignoreNoResponders && errors.Is(err, events.ErrRequestNoResponders) { | ||
span.AddEvent("ignored no request responders") | ||
|
||
return nil | ||
} | ||
|
||
errs = append(errs, err) | ||
} | ||
|
||
if resp != nil { | ||
if resp.Error() != nil { | ||
errs = append(errs, err) | ||
} | ||
|
||
errs = append(errs, resp.Message().Errors...) | ||
} | ||
|
||
err = multierr.Combine(errs...) | ||
|
||
if err != nil { | ||
span.RecordError(err) | ||
span.SetStatus(codes.Error, err.Error()) | ||
|
||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// CreateAuthRelationships publishes a create auth relationship request, blocking until a response has been received. | ||
func (p *Permissions) CreateAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error { | ||
request := events.AuthRelationshipRequest{ | ||
Action: events.WriteAuthRelationshipAction, | ||
ObjectID: resourceID, | ||
Relations: relations, | ||
} | ||
|
||
return p.submitAuthRelationshipRequest(ctx, topic, request) | ||
} | ||
|
||
// DeleteAuthRelationships publishes a delete auth relationship request, blocking until a response has been received. | ||
func (p *Permissions) DeleteAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error { | ||
request := events.AuthRelationshipRequest{ | ||
Action: events.DeleteAuthRelationshipAction, | ||
ObjectID: resourceID, | ||
Relations: relations, | ||
} | ||
|
||
return p.submitAuthRelationshipRequest(ctx, topic, request) | ||
} | ||
|
||
// CreateAuthRelationships publishes a create auth relationship request, blocking until a response has been received. | ||
func CreateAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error { | ||
handler, ok := ctx.Value(AuthRelationshipRequestHandlerCtxKey).(AuthRelationshipRequestHandler) | ||
if !ok { | ||
return ErrPermissionsMiddlewareMissing | ||
} | ||
|
||
return handler.CreateAuthRelationships(ctx, topic, resourceID, relations...) | ||
} | ||
|
||
// DeleteAuthRelationships publishes a delete auth relationship request, blocking until a response has been received. | ||
func DeleteAuthRelationships(ctx context.Context, topic string, resourceID gidx.PrefixedID, relations ...events.AuthRelationshipRelation) error { | ||
handler, ok := ctx.Value(AuthRelationshipRequestHandlerCtxKey).(AuthRelationshipRequestHandler) | ||
if !ok { | ||
return ErrPermissionsMiddlewareMissing | ||
} | ||
|
||
return handler.DeleteAuthRelationships(ctx, topic, resourceID, relations...) | ||
} |
Oops, something went wrong.