Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
100 changes: 21 additions & 79 deletions SpiceDb/Api/SpiceDbPermissions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using Authzed.Api.V1;
using Google.Protobuf.Collections;
using Grpc.Core;
Expand Down Expand Up @@ -32,21 +31,12 @@ public async Task<List<string>> GetResourcePermissionsAsync(string resourceType,
{
LookupResourcesRequest req = new LookupResourcesRequest
{
Consistency = new Authzed.Api.V1.Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
Permission = permission,
ResourceObjectType = resourceType,
Subject = new SubjectReference { Object = new ObjectReference { ObjectType = subjectType, ObjectId = subjectId } }
};

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}

//Server streaming call, reads messages streamed from the service
using var call = _acl!.LookupResources(req);

Expand All @@ -68,20 +58,11 @@ public async Task<List<string>> GetResourcePermissionsAsync(string resourceType,
{
var req = new ExpandPermissionTreeRequest
{
Consistency = new Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
Permission = permission,
Resource = new ObjectReference { ObjectType = resourceType, ObjectId = resourceId }
};

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}

return await _acl!.ExpandPermissionTreeAsync(req);
}

Expand All @@ -96,22 +77,13 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,
{
var req = new CheckPermissionRequest
{
Consistency = new Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
Permission = permission,
Resource = new ObjectReference { ObjectType = resourceType, ObjectId = resourceId },
Subject = new SubjectReference { Object = new ObjectReference { ObjectType = subjectType, ObjectId = subjectId } },
Context = context?.ToStruct()
};

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}

var call = await _acl!.CheckPermissionAsync(req);

return new PermissionResponse
Expand All @@ -131,20 +103,11 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,
{
var req = new CheckBulkPermissionsRequest()
{
Consistency = new Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
};

req.Items.AddRange(items);

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}

var call = await _acl!.CheckBulkPermissionsAsync(req);

if (call == null)
Expand Down Expand Up @@ -189,23 +152,14 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,
{
LookupSubjectsRequest req = new LookupSubjectsRequest
{
Consistency = new Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
Resource = new ObjectReference { ObjectType = resourceType, ObjectId = resourceId },
Permission = permission,
SubjectObjectType = subjectType,
OptionalSubjectRelation = optionalSubjectRelation,
Context = context?.ToStruct()
};

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}


using var call = _acl!.LookupSubjects(req);

await foreach (var resp in call.ResponseStream.ReadAllAsync())
Expand Down Expand Up @@ -251,7 +205,7 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,
{
LookupResourcesRequest req = new LookupResourcesRequest
{
Consistency = new Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
ResourceObjectType = resourceType,
Permission = permission,
Subject = new SubjectReference
Expand All @@ -262,18 +216,8 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,
Context = context?.ToStruct()
};

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}

using var call = _acl!.LookupResources(req);


await foreach (var resp in call.ResponseStream.ReadAllAsync())
{
if (resp is null) continue;
Expand Down Expand Up @@ -310,23 +254,14 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,

ReadRelationshipsRequest req = new ReadRelationshipsRequest()
{
Consistency = new Consistency { MinimizeLatency = true, AtExactSnapshot = zedToken },
Consistency = CreateConsistency(zedToken, cacheFreshness),
RelationshipFilter = CreateRelationshipFilter(resourceType, optionalResourceId, optionalRelation, optionalSubjectType, optionalSubjectId, optionalSubjectRelation),
OptionalLimit = limit != null ? Math.Clamp((uint)limit, 0, 1000) : 0,
OptionalCursor = cursor is null ? null : new Authzed.Api.V1.Cursor
{
Token = cursor.Token
}
};

if (cacheFreshness == CacheFreshness.AtLeastAsFreshAs)
{
req.Consistency.AtLeastAsFresh = zedToken;
}
else if (cacheFreshness == CacheFreshness.MustRefresh || zedToken == null)
{
req.Consistency.FullyConsistent = true;
}

using var call = _acl!.ReadRelationships(req);

Expand Down Expand Up @@ -355,7 +290,6 @@ public async Task<PermissionResponse> CheckPermissionAsync(string resourceType,
}
}


public bool UpdateRelationships(ref RepeatedField<RelationshipUpdate> updateCollection, RelationshipUpdate updateItem, bool addOrDelete = true)
{
if (addOrDelete)
Expand Down Expand Up @@ -419,8 +353,7 @@ public RelationshipUpdate GetRelationshipUpdate(string resourceType, string reso
}
};
}



public async Task<WriteRelationshipsResponse> WriteRelationshipsAsync(RepeatedField<RelationshipUpdate> updateCollection, RepeatedField<Authzed.Api.V1.Precondition>? optionalPreconditions = null)
{
WriteRelationshipsRequest req = new WriteRelationshipsRequest()
Expand All @@ -432,8 +365,6 @@ public async Task<WriteRelationshipsResponse> WriteRelationshipsAsync(RepeatedFi
return await _acl!.WriteRelationshipsAsync(req);
}



public async Task<ZedToken> UpdateRelationshipAsync(string resourceType, string resourceId, string relation,
string subjectType, string subjectId, string optionalSubjectRelation = "",
RelationshipUpdate.Types.Operation operation = RelationshipUpdate.Types.Operation.Touch, Caveat? caveat = null)
Expand Down Expand Up @@ -495,4 +426,15 @@ private static Authzed.Api.V1.RelationshipFilter CreateRelationshipFilter(string

return filter;
}

private static Consistency CreateConsistency(ZedToken? zedToken, CacheFreshness cacheFreshness) =>
(cacheFreshness, zedToken) switch
{
(CacheFreshness.AnyFreshness, _) => new Consistency { MinimizeLatency = true },
(CacheFreshness.MustRefresh, _) => new Consistency { FullyConsistent = true},
(CacheFreshness.AtLeastAsFreshAs, not null) => new Consistency { AtLeastAsFresh = zedToken },
(CacheFreshness.AtExactSnapshot, not null) => new Consistency { AtExactSnapshot = zedToken },
(CacheFreshness.AtExactSnapshot or CacheFreshness.AtLeastAsFreshAs, null) => throw new ArgumentException("ZedToken must be provided when using AtExactSnapshot or AtLeastAsFreshAs"),
_ => throw new ArgumentOutOfRangeException(nameof(cacheFreshness), cacheFreshness, "Invalid cache freshness value")
};
}
3 changes: 2 additions & 1 deletion SpiceDb/Enum/CacheFreshness.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public enum CacheFreshness
{
AnyFreshness,
AtLeastAsFreshAs,
MustRefresh
MustRefresh,
AtExactSnapshot
}
Loading