Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RavenDB IsOperationAllowedOnDocument not supported in Embedded Mode

Tags:

ravendb

RavenDB throws InvalidOperationException when IsOperationAllowedOnDocument is called using embedded mode.

I can see in the IsOperationAllowedOnDocument implementation a clause checking for calls in embedded mode.

namespace Raven.Client.Authorization
{
    public static class AuthorizationClientExtensions
    {
        public static OperationAllowedResult[] IsOperationAllowedOnDocument(this ISyncAdvancedSessionOperation session, string userId, string operation, params string[] documentIds)
        {
            var serverClient = session.DatabaseCommands as ServerClient;
            if (serverClient == null)
                throw new InvalidOperationException("Cannot get whatever operation is allowed on document in embedded mode.");

Is there a workaround for this other than not using embedded mode?

Thanks for your time.

like image 779
santiagovm Avatar asked Oct 11 '12 22:10

santiagovm


2 Answers

I encountered the same situation while writing some unit tests. The solution James provided worked; however, it resulted in having one code path for the unit test and another path for the production code, which defeated the purpose of the unit test. We were able to create a second document store and connect it to the first document store which allowed us to then access the authorization extension methods successfully. While this solution would probably not be good for production code (because creating Document Stores is expensive) it works nicely for unit tests. Here is a code sample:

using (var documentStore = new EmbeddableDocumentStore
        { RunInMemory = true,
          UseEmbeddedHttpServer = true,
          Configuration = {Port = EmbeddedModePort} })
{
    documentStore.Initialize();
    var url = documentStore.Configuration.ServerUrl;

    using (var docStoreHttp = new DocumentStore {Url = url})
    {
        docStoreHttp.Initialize();

        using (var session = docStoreHttp.OpenSession())
        {
            // now you can run code like:
            // session.GetAuthorizationFor(),
            // session.SetAuthorizationFor(),
            // session.Advanced.IsOperationAllowedOnDocument(),
            // etc...
        }
    }
}

There are couple of other items that should be mentioned:

  1. The first document store needs to be run with the UseEmbeddedHttpServer set to true so that the second one can access it.
  2. I created a constant for the Port so it would be used consistently and ensure use of a non reserved port.
like image 196
Donovan R Avatar answered Nov 15 '22 07:11

Donovan R


I encountered this as well. Looking at the source, there's no way to do that operation as written. Not sure if there's some intrinsic reason why since I could easily replicate the functionality in my app by making a http request directly for the same info:

HttpClient http = new HttpClient();
http.BaseAddress = new Uri("http://localhost:8080");
var url = new StringBuilder("/authorization/IsAllowed/")
    .Append(Uri.EscapeUriString(userid))
    .Append("?operation=")
    .Append(Uri.EscapeUriString(operation)
    .Append("&id=").Append(Uri.EscapeUriString(entityid));
http.GetStringAsync(url.ToString()).ContinueWith((response) =>
{
    var results = _session.Advanced.DocumentStore.Conventions.CreateSerializer()
        .Deserialize<OperationAllowedResult[]>(
            new RavenJTokenReader(RavenJToken.Parse(response.Result)));
}).Wait();
like image 40
James Avatar answered Nov 15 '22 09:11

James