Permalink
Browse files

Will now properly calculate ETag for IsAllowed http call

  • Loading branch information...
1 parent c431b1b commit 4a6686055997c24eb3382c3467a9adef6c502706 @ayende ayende committed Aug 23, 2011
Showing with 70 additions and 20 deletions.
  1. +70 −20 Bundles/Raven.Bundles.Authorization/Responders/IsAllowed.cs
@@ -1,8 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Security.Cryptography;
+using Raven.Abstractions.Data;
+using Raven.Bundles.Authorization.Model;
using Raven.Database.Server.Responders;
using Raven.Http.Abstractions;
using Raven.Http.Extensions;
+using System.Linq;
+using Raven.Abstractions.Extensions;
namespace Raven.Bundles.Authorization.Responders
{
@@ -15,7 +20,7 @@ public override string UrlPattern
public override string[] SupportedVerbs
{
- get { return new string[]{"GET"}; }
+ get { return new string[] { "GET" }; }
}
public override void Respond(IHttpContext context)
@@ -33,34 +38,79 @@ public override void Respond(IHttpContext context)
return;
}
- var list = new List<OperationAllowedResult>();
+
// we don't want security to take hold when we are trying to ask about security
- using (Database.DisableAllTriggersForCurrentThread())
+ using (Database.DisableAllTriggersForCurrentThread())
{
- foreach (var docId in docIds)
+ var documents = docIds.Select(docId=>Database.GetDocumentMetadata(docId, transactionInformation)).ToArray();
+ var etag = CalculateEtag(documents, userId);
+ if (context.MatchEtag(etag))
{
- var document = Database.GetDocumentMetadata(docId, transactionInformation);
+ context.SetStatusToNotModified();
+ return;
+ }
- if (document == null)
+ context.Response.AddHeader("ETag", etag.ToString());
+ context.WriteJson(GenerateAuthorizationResponse(documents, docIds, operation, userId));
+ }
+ }
+
+ private List<OperationAllowedResult> GenerateAuthorizationResponse(JsonDocumentMetadata[] documents, string[] docIds, string operation, string userId)
+ {
+ var list = new List<OperationAllowedResult>();
+ for (var index = 0; index < documents.Length; index++)
+ {
+ var document = documents[index];
+ var docId = docIds[index];
+ if (document == null)
+ {
+ list.Add(new OperationAllowedResult
{
- list.Add(new OperationAllowedResult
+ IsAllowed = false,
+ Reasons = new List<string>
{
- IsAllowed = false,
- Reasons = new List<string>
- {
- "Document " + docId + " does not exists"
- }
- });
- continue;
- }
- var reasons = new List<string>();
- var authorizationDecisions = new AuthorizationDecisions(Database);
- var isAllowed = authorizationDecisions.IsAllowed(userId, operation, docId, document.Metadata, reasons.Add);
+ "Document " + docId + " does not exists"
+ }
+ });
+ continue;
+ }
+ var reasons = new List<string>();
+ var authorizationDecisions = new AuthorizationDecisions(Database);
+ var isAllowed = authorizationDecisions.IsAllowed(userId, operation, docId, document.Metadata, reasons.Add);
+
+ list.Add(new OperationAllowedResult {IsAllowed = isAllowed, Reasons = reasons});
+ }
+ return list;
+ }
+
+ private Guid CalculateEtag(IEnumerable<JsonDocumentMetadata> documents, string userId)
+ {
+ Guid etag;
+
+ using(var md5 = MD5.Create())
+ {
+ var etags =new List<byte>();
+
+ etags.AddRange(documents.SelectMany(x => x == null ? Guid.Empty.ToByteArray() : (x.Etag ?? Guid.Empty).ToByteArray()));
- list.Add(new OperationAllowedResult{ IsAllowed = isAllowed, Reasons = reasons });
+ var userDoc = Database.Get(userId, null);
+ if(userDoc == null)
+ {
+ etags.AddRange(Guid.Empty.ToByteArray());
+ }
+ else
+ {
+ etags.AddRange((userDoc.Etag ?? Guid.Empty).ToByteArray());
+ var user = userDoc.DataAsJson.JsonDeserialization<AuthorizationUser>();
+ foreach (var roleMetadata in user.Roles.Select(role => Database.GetDocumentMetadata(role, null)))
+ {
+ etags.AddRange(roleMetadata == null ? Guid.Empty.ToByteArray() : (roleMetadata.Etag ?? Guid.Empty).ToByteArray());
+ }
}
+
+ etag = new Guid(md5.ComputeHash(etags.ToArray()));
}
- context.WriteJson(list);
+ return etag;
}
}
}

0 comments on commit 4a66860

Please sign in to comment.