locked
Angebot eines Data Service einschränken RRS feed

  • Frage

  • Halle Miteinander,

    ich habe einen WCF Data Service mit u.a. diesen Entitäten:

    AKTEBENUTZER, AKTE, VORGANG

    Die Abhängigkeit zwischen diesen sieht so aus:

    AKTEBENUTZER -> AKTE -> VORGANG

    Mein Vorhaben:

    Es sollen aus AKTEBENUTZER -> AKTE -> VORGANG nur Daten geliefert werden, die dem am Service angemeldeten Benutzer zugeordnet sind. Der Direktzugriff auf AKTE oder VORGANG soll verhindert werden.

    Gibt es eine Möglichkeit, den Dienst so zu konfigurieren, dass für AKTE und VORGANG nur die Schemainformationen publiziert werden und auf die Daten nur über den Abhängigkeitspfad zugegriffen werden kann?

    Schönen Dank schon mal

    Rolf


    Montag, 5. Dezember 2016 06:20

Antworten

  • Hallo Dimitar und alle anderen,

    Meine Vermutung, dass es mit dem QueryInterceptor geht, traf zu. Alles läuft wie es laufen soll.

    Hier noch der Quellcode als Beispiel:

    //------------------------------------------------------------------------------
    // <copyright file="WebDataService.svc.cs" company="Microsoft">
    //     Copyright (c) Microsoft Corporation.  All rights reserved.
    // </copyright>
    //------------------------------------------------------------------------------
    using System;
    using System.Data.Services;
    using System.Data.Services.Common;
    using System.Data.Services.Providers;
    using System.Linq;
    using System.Linq.Expressions;
    using System.ServiceModel;
    
    namespace FarmexDBS.IR100.WebApplication
    {
        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
        public class IR100WcfDataService : EntityFrameworkDataService< MyModel >
        {
            
            private static string AngemeldeterBenutzer = "user01";
    
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
                // Examples:
                // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
                // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
                config.UseVerboseErrors = true;
    
                config.SetEntitySetAccessRule("AKTE", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("AKTEBENUTZER", EntitySetRights.None);
                config.SetEntitySetAccessRule("DOKUMENT", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("MASSNAHME", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("VORGANG", EntitySetRights.AllRead);
            }
    
            [QueryInterceptor("AKTE")]
            public Expression<Func<AKTE, bool>> FilterAkten()
            {
                return a => a.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer).Count() > 0;
            }
    
            [QueryInterceptor("VORGANG")]
            public Expression<Func<VORGANG,bool>> FilterVorgaenge()
            {
                return v=>v.AKTE.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer).Count() > 0;
            }
    
            [QueryInterceptor("MASSNAHME")]
            public Expression<Func<MASSNAHME, bool>> FilterMassnahmen()
            {
                return m => m.VORGANG.AKTE.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer).Count() > 0;
            }
    
            [QueryInterceptor("DOKUMENT")]
            public Expression<Func<DOKUMENT, bool>> FilterDokumente()
            {
                return d => d.VORGAENGE.SelectMany(v=>v.AKTE.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer)).Count() > 0;
            }
        }
    }
    

    Dienstag, 6. Dezember 2016 11:36

Alle Antworten

  • Hallo Rolf,

    Hast Du es mit der DataServiceConfiguration-Klasse versucht? Hoffentlich hilft Dir die SetEntitySetAccessRule-Methode weiter:
    DataServiceConfiguration.SetEntitySetAccessRule-Methode: (String, EntitySetRights)

    Befinden sich Akte und Vorgang einerseits und Aktebenutzer andererseits in zwei unterschiedlichen Entitätsmengen?

    Gruß,
    Dimitar


    Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.

    Dienstag, 6. Dezember 2016 06:17
    Moderator
  • Hallo Dimitar,

    danke für Deine Antwort.

    Zu Frage eins:
    Die SetEntitySetAccessRule-Methode hilft mir leider nicht weiter. Damit kann ich nur die Art des Datenzugriffs regeln (Alle Rechte, Leserecht und wie viele auf einmal, verschiedene Ausprägungen des Schreibrechts und "keine Rechte"). Leider ist so, dass "keine Rechte" auch wirklich so gemeint ist. Es werden auch keine Schemainformationen bereitgestellt. Die brauche ich aber :-(.

    Zu Frage zwei:
    Ja, Aktebenutzer, Akte und Vorgang sind jeweils eine Entitätsmenge. 
    Auf Akte wird mit Aktebenutzer.Akten und auf Vorgang mit Akte.Vorgaenge zugegriffen.
    Der direkte Zugriff auf die Entitätsmengen Akte und Vorgang soll verhindert werden, damit ein Benutzer nicht an Akten und Vorgänge kommt, die ihm nicht zugeordnet sind.

    Mittlerweile bin ich auf das Interceptor-Konzept gestoßen.
    Ich vermute, dass ich mit QueryInterceptor("AKTE") und QueryInterceptor("VORGANG") zum Ziel komme.
    Leider bin ich bei Linq und Lambda ein ziemlicher Newbie.

    Schönen Gruß

    Rolf

    Dienstag, 6. Dezember 2016 09:05
  • Hallo Dimitar und alle anderen,

    Meine Vermutung, dass es mit dem QueryInterceptor geht, traf zu. Alles läuft wie es laufen soll.

    Hier noch der Quellcode als Beispiel:

    //------------------------------------------------------------------------------
    // <copyright file="WebDataService.svc.cs" company="Microsoft">
    //     Copyright (c) Microsoft Corporation.  All rights reserved.
    // </copyright>
    //------------------------------------------------------------------------------
    using System;
    using System.Data.Services;
    using System.Data.Services.Common;
    using System.Data.Services.Providers;
    using System.Linq;
    using System.Linq.Expressions;
    using System.ServiceModel;
    
    namespace FarmexDBS.IR100.WebApplication
    {
        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
        public class IR100WcfDataService : EntityFrameworkDataService< MyModel >
        {
            
            private static string AngemeldeterBenutzer = "user01";
    
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
                // Examples:
                // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
                // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
                config.UseVerboseErrors = true;
    
                config.SetEntitySetAccessRule("AKTE", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("AKTEBENUTZER", EntitySetRights.None);
                config.SetEntitySetAccessRule("DOKUMENT", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("MASSNAHME", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("VORGANG", EntitySetRights.AllRead);
            }
    
            [QueryInterceptor("AKTE")]
            public Expression<Func<AKTE, bool>> FilterAkten()
            {
                return a => a.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer).Count() > 0;
            }
    
            [QueryInterceptor("VORGANG")]
            public Expression<Func<VORGANG,bool>> FilterVorgaenge()
            {
                return v=>v.AKTE.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer).Count() > 0;
            }
    
            [QueryInterceptor("MASSNAHME")]
            public Expression<Func<MASSNAHME, bool>> FilterMassnahmen()
            {
                return m => m.VORGANG.AKTE.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer).Count() > 0;
            }
    
            [QueryInterceptor("DOKUMENT")]
            public Expression<Func<DOKUMENT, bool>> FilterDokumente()
            {
                return d => d.VORGAENGE.SelectMany(v=>v.AKTE.AKTENBENUTZER.
                    Where(ab => ab.REF_BENUTZER == AngemeldeterBenutzer)).Count() > 0;
            }
        }
    }
    

    Dienstag, 6. Dezember 2016 11:36