Skip to content

Commit

Permalink
Merge pull request #951 from Permify/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
tolgaOzen authored Dec 25, 2023
2 parents 00e2272 + 8b921ee commit 58c7bc7
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 28 deletions.
2 changes: 1 addition & 1 deletion docs/apidocs.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "Permify API",
"description": "Permify is an open source authorization service for creating fine-grained and scalable authorization systems.",
"version": "v0.6.4",
"version": "v0.6.5",
"contact": {
"name": "API Support",
"url": "https://github.com/Permify/permify/issues",
Expand Down
2 changes: 1 addition & 1 deletion internal/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var Identifier = xid.New().String()
*/
const (
// Version is the last release of the Permify (e.g. v0.1.0)
Version = "v0.6.4"
Version = "v0.6.5"

// Banner is the view for terminal.
Banner = `
Expand Down
5 changes: 3 additions & 2 deletions internal/storage/memory/dataReader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"strconv"
"time"

"github.com/Permify/permify/internal/storage/memory/constants"
"github.com/hashicorp/go-memdb"

"github.com/Permify/permify/internal/storage/memory/constants"

"github.com/Permify/permify/internal/storage"
"github.com/Permify/permify/internal/storage/memory/snapshot"
"github.com/Permify/permify/internal/storage/memory/utils"
Expand Down Expand Up @@ -198,7 +199,7 @@ func (r *DataReader) ReadAttributes(_ context.Context, tenantID string, filter *

// Get the result iterator using lower bound.
var result memdb.ResultIterator
result, err = txn.LowerBound(constants.RelationTuplesTable, index, args...)
result, err = txn.LowerBound(constants.AttributesTable, index, args...)
if err != nil {
return nil, database.NewNoopContinuousToken().Encode(), errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}
Expand Down
169 changes: 147 additions & 22 deletions internal/storage/memory/dataWriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func NewDataWriter(database *db.Memory) *DataWriter {
}

// WriteRelationships - Write a Relation to repository
func (r *DataWriter) Write(_ context.Context, tenantID string, tupleCollection *database.TupleCollection, attributesCollection *database.AttributeCollection) (token.EncodedSnapToken, error) {
func (w *DataWriter) Write(_ context.Context, tenantID string, tupleCollection *database.TupleCollection, attributesCollection *database.AttributeCollection) (token.EncodedSnapToken, error) {
var err error

tupleIterator := tupleCollection.CreateTupleIterator()
Expand All @@ -40,7 +40,7 @@ func (r *DataWriter) Write(_ context.Context, tenantID string, tupleCollection *
return token.NewNoopToken().Encode(), nil
}

txn := r.database.DB.Txn(true)
txn := w.database.DB.Txn(true)
defer txn.Abort()

for tupleIterator.HasNext() {
Expand All @@ -49,7 +49,7 @@ func (r *DataWriter) Write(_ context.Context, tenantID string, tupleCollection *
if srelation == tuple.ELLIPSIS {
srelation = ""
}
t := storage.RelationTuple{
if err = txn.Insert(constants.RelationTuplesTable, storage.RelationTuple{
ID: utils.RelationTuplesID.ID(),
TenantID: tenantID,
EntityType: bt.GetEntity().GetType(),
Expand All @@ -58,24 +58,21 @@ func (r *DataWriter) Write(_ context.Context, tenantID string, tupleCollection *
SubjectType: bt.GetSubject().GetType(),
SubjectID: bt.GetSubject().GetId(),
SubjectRelation: srelation,
}
if err = txn.Insert(constants.RelationTuplesTable, t); err != nil {
}); err != nil {
return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}
}

for attributeIterator.HasNext() {
at := attributeIterator.GetNext()

t := storage.Attribute{
if err = txn.Insert(constants.AttributesTable, storage.Attribute{
ID: utils.AttributesID.ID(),
TenantID: tenantID,
EntityType: at.GetEntity().GetType(),
EntityID: at.GetEntity().GetId(),
Attribute: at.GetAttribute(),
Value: at.GetValue(),
}
if err = txn.Insert(constants.AttributesTable, t); err != nil {
}); err != nil {
return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}
}
Expand All @@ -85,9 +82,9 @@ func (r *DataWriter) Write(_ context.Context, tenantID string, tupleCollection *
}

// Delete - Delete relationship from repository
func (r *DataWriter) Delete(_ context.Context, tenantID string, tupleFilter *base.TupleFilter, attributeFilter *base.AttributeFilter) (token.EncodedSnapToken, error) {
func (w *DataWriter) Delete(_ context.Context, tenantID string, tupleFilter *base.TupleFilter, attributeFilter *base.AttributeFilter) (token.EncodedSnapToken, error) {
var err error
txn := r.database.DB.Txn(true)
txn := w.database.DB.Txn(true)
defer txn.Abort()

tIndex, tArgs := utils.GetRelationTuplesIndexNameAndArgsByFilters(tenantID, tupleFilter)
Expand Down Expand Up @@ -118,11 +115,11 @@ func (r *DataWriter) Delete(_ context.Context, tenantID string, tupleFilter *bas

fit := memdb.NewFilterIterator(aIt, utils.FilterAttributesQuery(tenantID, attributeFilter))
for obj := fit.Next(); obj != nil; obj = fit.Next() {
t, ok := obj.(storage.RelationTuple)
t, ok := obj.(storage.Attribute)
if !ok {
return nil, errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String())
}
err = txn.Delete(constants.RelationTuplesTable, t)
err = txn.Delete(constants.AttributesTable, t)
if err != nil {
return nil, errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}
Expand All @@ -132,23 +129,151 @@ func (r *DataWriter) Delete(_ context.Context, tenantID string, tupleFilter *bas
return snapshot.NewToken(time.Now()).Encode(), nil
}

func (r *DataWriter) RunBundle(ctx context.Context, tenantID string, arguments map[string]string, b *base.DataBundle) (token token.EncodedSnapToken, err error) {
// RunBundle executes a bundle of operations in the context of a given tenant.
// It returns an EncodedSnapToken upon successful completion or an error if the operation fails.
func (w *DataWriter) RunBundle(
ctx context.Context,
tenantID string,
arguments map[string]string,
b *base.DataBundle,
) (token.EncodedSnapToken, error) {
txn := w.database.DB.Txn(true)
defer txn.Abort()

for _, op := range b.GetOperations() {
tupleCollection, attributeCollection, err := bundle.Operation(arguments, op)
tb, ab, err := bundle.Operation(arguments, op)
if err != nil {
return nil, err
}

// Write operation
if _, err = r.Write(ctx, tenantID, &tupleCollection.Write, &attributeCollection.Write); err != nil {
err = w.runOperation(ctx, txn, tenantID, tb, ab)
if err != nil {
return nil, err
}

// Delete operation
// if _, err = r.Delete(ctx, tenantID, &tupleCollection.Delete, &attributeCollection.Delete); err != nil {
// return nil, err
// }
}

// Commit the final transaction
txn.Commit()

return snapshot.NewToken(time.Now()).Encode(), nil
}

// runOperation processes and executes database operations defined in TupleBundle and AttributeBundle within a given transaction.
func (w *DataWriter) runOperation(
ctx context.Context,
txn *memdb.Txn,
tenantID string,
tb database.TupleBundle,
ab database.AttributeBundle,
) (err error) {
if len(tb.Write.GetTuples()) > 0 {
for titer := tb.Write.CreateTupleIterator(); titer.HasNext(); {
t := titer.GetNext()
srelation := t.GetSubject().GetRelation()
if srelation == tuple.ELLIPSIS {
srelation = ""
}

// Insert the tuple into the RelationTuplesTable
if err := txn.Insert(constants.RelationTuplesTable, storage.RelationTuple{
ID: utils.RelationTuplesID.ID(),
EntityID: t.GetEntity().GetId(),
EntityType: t.GetEntity().GetType(),
Relation: t.GetRelation(),
SubjectID: t.GetSubject().GetId(),
SubjectType: t.GetSubject().GetType(),
SubjectRelation: srelation,
TenantID: tenantID,
}); err != nil {
return err
}
}
}

if len(ab.Write.GetAttributes()) > 0 {
for aiter := ab.Write.CreateAttributeIterator(); aiter.HasNext(); {
a := aiter.GetNext()
if err := txn.Insert(constants.AttributesTable, storage.Attribute{
ID: utils.AttributesID.ID(),
EntityID: a.GetEntity().GetId(),
EntityType: a.GetEntity().GetType(),
Attribute: a.GetAttribute(),
Value: a.GetValue(),
TenantID: tenantID,
}); err != nil {
return err
}
}
}

if len(tb.Delete.GetTuples()) > 0 {
for titer := tb.Delete.CreateTupleIterator(); titer.HasNext(); {
next := titer.GetNext()
tupleFilter := &base.TupleFilter{
Entity: &base.EntityFilter{
Type: next.GetEntity().GetType(),
Ids: []string{next.GetEntity().GetId()},
},
Relation: next.GetRelation(),
Subject: &base.SubjectFilter{
Type: next.GetSubject().GetType(),
Ids: []string{next.GetSubject().GetId()},
Relation: next.GetSubject().GetRelation(),
},
}

tIndex, tArgs := utils.GetRelationTuplesIndexNameAndArgsByFilters(tenantID, tupleFilter)
var tit memdb.ResultIterator
tit, err = txn.Get(constants.RelationTuplesTable, tIndex, tArgs...)
if err != nil {
return errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}

tFit := memdb.NewFilterIterator(tit, utils.FilterRelationTuplesQuery(tenantID, tupleFilter))
for obj := tFit.Next(); obj != nil; obj = tFit.Next() {
t, ok := obj.(storage.RelationTuple)
if !ok {
return errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String())
}
err = txn.Delete(constants.RelationTuplesTable, t)
if err != nil {
return errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}
}
}
}

if len(ab.Delete.GetAttributes()) > 0 {
for aiter := ab.Delete.CreateAttributeIterator(); aiter.HasNext(); {
next := aiter.GetNext()
attributeFilter := &base.AttributeFilter{
Entity: &base.EntityFilter{
Type: next.GetEntity().GetType(),
Ids: []string{next.GetEntity().GetId()},
},
Attributes: []string{next.GetAttribute()},
}

aIndex, args := utils.GetAttributesIndexNameAndArgsByFilters(tenantID, attributeFilter)
var aIt memdb.ResultIterator
aIt, err = txn.Get(constants.AttributesTable, aIndex, args...)
if err != nil {
return errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}

fit := memdb.NewFilterIterator(aIt, utils.FilterAttributesQuery(tenantID, attributeFilter))
for obj := fit.Next(); obj != nil; obj = fit.Next() {
t, ok := obj.(storage.Attribute)
if !ok {
return errors.New(base.ErrorCode_ERROR_CODE_TYPE_CONVERSATION.String())
}
err = txn.Delete(constants.AttributesTable, t)
if err != nil {
return errors.New(base.ErrorCode_ERROR_CODE_EXECUTION.String())
}
}
}
}

return nil
}
Loading

0 comments on commit 58c7bc7

Please sign in to comment.