Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Change local_acp implementation to use acp_core #2691

Merged
merged 46 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
185ccec
refactor: replace Embedded ACP with ACP Core engine
Lodek Jun 6, 2024
bb0f676
doc: doc methods
Lodek Jun 5, 2024
1059f0a
test refactor wip
Lodek Jun 5, 2024
5aeab86
add_policy refactor
Lodek Jun 5, 2024
90cd3f1
fix: index test
Lodek Jun 5, 2024
4a555a4
fix p2p tests
Lodek Jun 5, 2024
4b233e9
fix: query tests
Lodek Jun 5, 2024
aa22100
schema test refactor
Lodek Jun 5, 2024
f108555
fix: acp integration
Lodek Jun 5, 2024
33b994c
test fixes
Lodek Jun 5, 2024
4b56a79
test fixes
Lodek Jun 6, 2024
c31efc8
doc: updated acp_local adapter docs
Lodek Jun 6, 2024
4ed1c0c
added defra policy abstraction
Lodek Jun 6, 2024
7e4982d
mod bump
Lodek Jun 6, 2024
dc907a9
fix: net peer tests
Lodek Jun 6, 2024
d5c1de1
remove helper methods from policy data types
Lodek Jun 6, 2024
a549c9d
fix: collection_description test fix
Lodek Jun 7, 2024
5af32f4
PR suggestins and toolchain update
Lodek Jun 7, 2024
edb060a
chore: update fixme docs
Lodek Jun 7, 2024
796454d
bump acp_core version
Lodek Jun 7, 2024
6682ba5
refactor identity
Lodek Jun 7, 2024
a198dd0
factor: Indetity DID generation and test fixes
Lodek Jun 7, 2024
3bcbc39
update license in file
Lodek Jun 7, 2024
cf27ec2
test: added missing tests
Lodek Jun 10, 2024
ee5fb03
refactor: identity returns error
Lodek Jun 11, 2024
dd34b38
refactor fixes
Lodek Jun 11, 2024
f5ceca9
Merge branch 'develop' into refactor/local-acp
Lodek Jun 11, 2024
d0db457
chore: go mod tidy
Lodek Jun 11, 2024
9308ad2
revert: change actor id to creator id in polcy create
Lodek Jun 11, 2024
d9cf7d6
test: FromPrivateKey, FromPublicKey
Lodek Jun 11, 2024
df10e84
fix: typo
Lodek Jun 11, 2024
67cb1c1
identity and did providers
Lodek Jun 13, 2024
71364aa
identity refactor
Lodek Jun 13, 2024
04cc0b7
ci fix
Lodek Jun 13, 2024
547e194
fix typo
Lodek Jun 13, 2024
b80aa03
provier rename
Lodek Jun 13, 2024
549c406
Revert "identity refactor"
Lodek Jun 14, 2024
6dbd782
producer refactor
Lodek Jun 14, 2024
6982d9e
cleanup
Lodek Jun 14, 2024
6205c7b
lint fix
Lodek Jun 14, 2024
568a46b
Merge branch 'develop' into refactor/local-acp
Lodek Jun 14, 2024
d28db70
revert identity provider
Lodek Jun 14, 2024
3b3bbe8
refactor: make identity err func private
Lodek Jun 14, 2024
e1135a1
revert policy marshal type location
Lodek Jun 14, 2024
10f5826
Merge branch 'develop' into refactor/local-acp
Lodek Jun 19, 2024
80beb43
chore: mod tidy
Lodek Jun 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 136 additions & 71 deletions acp/acp_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,61 @@

import (
"context"
"errors"

protoTypes "github.com/cosmos/gogoproto/types"
"github.com/sourcenetwork/acp_core/pkg/auth"
"github.com/sourcenetwork/acp_core/pkg/engine"
"github.com/sourcenetwork/acp_core/pkg/runtime"
"github.com/sourcenetwork/acp_core/pkg/types"
"github.com/sourcenetwork/immutable"
"github.com/sourcenetwork/sourcehub/x/acp/embedded"
"github.com/sourcenetwork/sourcehub/x/acp/types"
"github.com/valyala/fastjson"
)

const localACPStoreName = "local_acp"

// ACPLocal represents a local acp implementation that makes no remote calls.
type ACPLocal struct {
pathToStore immutable.Option[string]
localACP *embedded.LocalACP
engine types.ACPEngineServer
manager runtime.RuntimeManager
}

var _ sourceHubClient = (*ACPLocal)(nil)

func mapACPCorePolicy(pol *types.Policy) policy {
resources := make(map[string]*resource)
for _, coreResource := range pol.Resources {
resource := mapACPCoreResource(coreResource)
resources[resource.Name] = resource
}

return policy{
ID: pol.Id,
Resources: resources,
}
}

func mapACPCoreResource(policy *types.Resource) *resource {
perms := make(map[string]*permission)
for _, corePermission := range policy.Permissions {
perm := mapACPCorePermission(corePermission)
perms[perm.Name] = perm
}

return &resource{
Name: policy.Name,
Permissions: perms,
}
}

func mapACPCorePermission(perm *types.Permission) *permission {
return &permission{
Name: perm.Name,
Expression: perm.Expression,
}
}

func (l *ACPLocal) Init(ctx context.Context, path string) {
if path == "" {
l.pathToStore = immutable.None[string]()
Expand All @@ -36,73 +76,84 @@
}

func (l *ACPLocal) Start(ctx context.Context) error {
var localACP embedded.LocalACP
var manager runtime.RuntimeManager
var err error
var opts []runtime.Opt
var storeLocation string

if !l.pathToStore.HasValue() { // Use a non-persistent, i.e. in memory store.
localACP, err = embedded.NewLocalACP(
embedded.WithInMemStore(),
)

if err != nil {
return NewErrInitializationOfACPFailed(err, "Local", "in-memory")
}
storeLocation = "in-memory"
opts = append(opts, runtime.WithMemKV())
} else { // Use peristent storage.
acpStorePath := l.pathToStore.Value() + "/" + embedded.DefaultDataDir
localACP, err = embedded.NewLocalACP(
embedded.WithPersistentStorage(acpStorePath),
)
if err != nil {
return NewErrInitializationOfACPFailed(err, "Local", l.pathToStore.Value())
}
storeLocation = l.pathToStore.Value()
acpStorePath := storeLocation + "/" + localACPStoreName
opts = append(opts, runtime.WithPersistentKV(acpStorePath))
}

manager, err = runtime.NewRuntimeManager(opts...)
if err != nil {
return NewErrInitializationOfACPFailed(err, "Local", storeLocation)

Check warning on line 95 in acp/acp_local.go

View check run for this annotation

Codecov / codecov/patch

acp/acp_local.go#L95

Added line #L95 was not covered by tests
}

l.localACP = &localACP
l.manager = manager
l.engine = engine.NewACPEngine(manager)
return nil
}

func (l *ACPLocal) Close() error {
return l.localACP.Close()
return l.manager.Terminate()
Lodek marked this conversation as resolved.
Show resolved Hide resolved
}

func (l *ACPLocal) AddPolicy(
ctx context.Context,
creatorID string,
Lodek marked this conversation as resolved.
Show resolved Hide resolved
policy string,
policyMarshalType types.PolicyMarshalingType,
creationTime *protoTypes.Timestamp,
) (string, error) {
createPolicy := types.MsgCreatePolicy{
Creator: creatorID,
principal, err := auth.NewDIDPrincipal(creatorID)
if err != nil {
return "", newErrInvalidActorID(err, creatorID)
Lodek marked this conversation as resolved.
Show resolved Hide resolved
}
ctx = auth.InjectPrincipal(ctx, principal)

marshalType := types.PolicyMarshalingType_SHORT_YAML
if isJSON := fastjson.Validate(policy) == nil; isJSON { // Detect JSON format.
marshalType = types.PolicyMarshalingType_SHORT_JSON
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Why was the detection moved from source_hub_client into the local acp logic? Wouldn't this be nicer for @AndrewSisley's remote acp implementation as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, fair. I'll add a custom Defra type for it, as I did for the Registration Result

Copy link
Member

@shahzadlone shahzadlone Jun 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just leaving as it was before should be fine? why do we need a custom type?

EDIT: I see what you mean, just reviewed the last commit


createPolicy := types.CreatePolicyRequest{
Policy: policy,
MarshalType: policyMarshalType,
MarshalType: marshalType,
CreationTime: protoTypes.TimestampNow(),
}

createPolicyResponse, err := l.localACP.GetMsgService().CreatePolicy(
l.localACP.GetCtx(),
&createPolicy,
)
response, err := l.engine.CreatePolicy(ctx, &createPolicy)

if err != nil {
return "", err
}

return createPolicyResponse.Policy.Id, nil
return response.Policy.Id, nil
}

func (l *ACPLocal) Policy(
ctx context.Context,
policyID string,
) (*types.Policy, error) {
queryPolicyResponse, err := l.localACP.GetQueryService().Policy(
l.localACP.GetCtx(),
&types.QueryPolicyRequest{Id: policyID},
)
) (immutable.Option[policy], error) {
none := immutable.None[policy]()

request := types.GetPolicyRequest{Id: policyID}
response, err := l.engine.GetPolicy(ctx, &request)

if err != nil {
return nil, err
if errors.Is(err, types.ErrPolicyNotFound) {
return none, nil
}
return none, err

Check warning on line 152 in acp/acp_local.go

View check run for this annotation

Codecov / codecov/patch

acp/acp_local.go#L152

Added line #L152 was not covered by tests
}

return queryPolicyResponse.Policy, nil
policy := mapACPCorePolicy(response.Policy)
return immutable.Some(policy), nil
}

func (l *ACPLocal) RegisterObject(
Expand All @@ -112,36 +163,51 @@
resourceName string,
objectID string,
creationTime *protoTypes.Timestamp,
) (types.RegistrationResult, error) {
registerDocResponse, err := l.localACP.GetMsgService().RegisterObject(
l.localACP.GetCtx(),
&types.MsgRegisterObject{
Creator: actorID,
PolicyId: policyID,
Object: types.NewObject(resourceName, objectID),
CreationTime: creationTime,
},
)
) (RegistrationResult, error) {
principal, err := auth.NewDIDPrincipal(actorID)
if err != nil {
return RegistrationResult_NoOp, newErrInvalidActorID(err, actorID)
}

ctx = auth.InjectPrincipal(ctx, principal)
req := types.RegisterObjectRequest{
PolicyId: policyID,
Object: types.NewObject(resourceName, objectID),
CreationTime: creationTime,
}

registerDocResponse, err := l.engine.RegisterObject(ctx, &req)

if err != nil {
return types.RegistrationResult(0), err
return RegistrationResult_NoOp, err
}

return registerDocResponse.Result, nil
result := RegistrationResult(registerDocResponse.Result)
return result, nil
}

func (l *ACPLocal) ObjectOwner(
ctx context.Context,
policyID string,
resourceName string,
objectID string,
) (*types.QueryObjectOwnerResponse, error) {
return l.localACP.GetQueryService().ObjectOwner(
l.localACP.GetCtx(),
&types.QueryObjectOwnerRequest{
PolicyId: policyID,
Object: types.NewObject(resourceName, objectID),
},
)
) (immutable.Option[string], error) {
none := immutable.None[string]()

req := types.GetObjectRegistrationRequest{
PolicyId: policyID,
Object: types.NewObject(resourceName, objectID),
}
result, err := l.engine.GetObjectRegistration(ctx, &req)
if err != nil {
return none, err
}

if result.IsRegistered {
return immutable.Some(result.OwnerId), nil
}

return none, nil
}

func (l *ACPLocal) VerifyAccessRequest(
Expand All @@ -152,26 +218,25 @@
resourceName string,
docID string,
) (bool, error) {
checkDocResponse, err := l.localACP.GetQueryService().VerifyAccessRequest(
l.localACP.GetCtx(),
&types.QueryVerifyAccessRequestRequest{
PolicyId: policyID,
AccessRequest: &types.AccessRequest{
Operations: []*types.Operation{
{
Object: types.NewObject(resourceName, docID),
Permission: permission.String(),
},
},
Actor: &types.Actor{
Id: actorID,
req := types.VerifyAccessRequestRequest{
PolicyId: policyID,
AccessRequest: &types.AccessRequest{
Operations: []*types.Operation{
{
Object: types.NewObject(resourceName, docID),
Permission: permission.String(),
},
},
Actor: &types.Actor{
Id: actorID,
},
},
)
}
resp, err := l.engine.VerifyAccessRequest(ctx, &req)

if err != nil {
return false, err
}

return checkDocResponse.Valid, nil
return resp.Valid, nil
}
Loading
Loading