/// <summary>
        /// Helper method performs a query operation against a given proxy instance.
        /// </summary>
        /// <param name="domainService">The type of <see cref="DomainService"/> to perform this query operation against.</param>
        /// <param name="context">The current context.</param>
        /// <param name="domainServiceInstances">The list of tracked <see cref="DomainService"/> instances that any newly created
        /// <see cref="DomainServices"/> will be added to.</param>
        /// <param name="queryName">The name of the query to invoke.</param>
        /// <param name="parameters">The query parameters.</param>
        /// <returns>The query results. May be null if there are no query results.</returns>
        /// <exception cref="ArgumentNullException">if <paramref name="context"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="queryName"/> is null or an empty string.</exception>
        /// <exception cref="InvalidOperationException">if no match query operation exists on the <paramref name="context"/>.</exception>
        /// <exception cref="OperationException">if operation errors are thrown during execution of the query operation.</exception>
        public static IEnumerable Query(Type domainService, DomainServiceContext context, IList <DomainService> domainServiceInstances, string queryName, object[] parameters)
        {
            context = new DomainServiceContext(context, DomainOperationType.Query);
            DomainService            service            = CreateDomainServiceInstance(domainService, context, domainServiceInstances);
            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     queryOperation     = serviceDescription.GetQueryMethod(queryName);

            if (queryOperation == null)
            {
                string errorMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resource.DomainServiceProxy_QueryOperationNotFound,
                        queryName,
                        domainService);

                throw new InvalidOperationException(errorMessage);
            }

            int totalCount;
            IEnumerable <ValidationResult> validationErrors;

            object[]         parameterValues  = parameters ?? new object[0];
            QueryDescription queryDescription = new QueryDescription(queryOperation, parameterValues);

            IEnumerable result = service.Query(queryDescription, out validationErrors, out totalCount);

            if (validationErrors != null && validationErrors.Any())
            {
                IEnumerable <ValidationResultInfo> operationErrors = validationErrors.Select(ve => new ValidationResultInfo(ve.ErrorMessage, ve.MemberNames));
                throw new OperationException(Resource.DomainServiceProxy_OperationError, operationErrors);
            }

            return(result);
        }
Пример #2
0
        public async Task DomainService_DirectQuery()
        {
            DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(TestDomainServices.EF.Catalog));

            TestDomainServices.EF.Catalog service = new TestDomainServices.EF.Catalog();
            DomainServiceContext          dsc     = new DomainServiceContext(new MockDataService(new MockUser("mathew")
            {
                IsAuthenticated = true
            }), DomainOperationType.Query);

            service.Initialize(dsc);

            DomainOperationEntry queryOperation = description.GetQueryMethod("GetPurchaseOrders");

            ServiceQuery serviceQuery = new ServiceQuery();

            serviceQuery.QueryParts = new ServiceQueryPart[]
            {
                new ServiceQueryPart("where", "(it.Freight!=0)"),
                new ServiceQueryPart("take", "1")
            };

            QueryResult <AdventureWorksModel.PurchaseOrder> result = await QueryProcessor.ProcessAsync <AdventureWorksModel.PurchaseOrder>(service, queryOperation, Array.Empty <object>(), serviceQuery);

            Assert.AreEqual(1, result.RootResults.Count());
        }
Пример #3
0
        public void DomainService_DirectQuery()
        {
            DomainServiceDescription description = DomainServiceDescription.GetDescription(typeof(TestDomainServices.EF.Catalog));

            TestDomainServices.EF.Catalog service = new TestDomainServices.EF.Catalog();
            DomainServiceContext          dsc     = new DomainServiceContext(new MockDataService(new MockUser("mathew")
            {
                IsAuthenticated = true
            }), DomainOperationType.Query);

            service.Initialize(dsc);

            DomainOperationEntry queryOperation = description.GetQueryMethod("GetPurchaseOrders");

            ServiceQuery serviceQuery = new ServiceQuery();

            serviceQuery.QueryParts = new ServiceQueryPart[]
            {
                new ServiceQueryPart("where", "(it.Freight!=0)"),
                new ServiceQueryPart("take", "1")
            };

            IEnumerable <ValidationResult> validationErrors;
            int totalCount;
            QueryResult <AdventureWorksModel.PurchaseOrder> result = QueryProcessor.Process <AdventureWorksModel.PurchaseOrder>(service, queryOperation, new object[0], serviceQuery, out validationErrors, out totalCount);

            Assert.AreEqual(1, result.RootResults.Count());
        }
        /// <summary>
        /// Helper method performs a query operation against a given proxy instance.
        /// </summary>
        /// <param name="domainService">The type of <see cref="DomainService"/> to perform this query operation against.</param>
        /// <param name="context">The current context.</param>
        /// <param name="domainServiceInstances">The list of tracked <see cref="DomainService"/> instances that any newly created
        /// <see cref="DomainServices"/> will be added to.</param>
        /// <param name="queryName">The name of the query to invoke.</param>
        /// <param name="parameters">The query parameters.</param>
        /// <returns>The query results. May be null if there are no query results.</returns>
        /// <exception cref="ArgumentNullException">if <paramref name="context"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="queryName"/> is null or an empty string.</exception>
        /// <exception cref="InvalidOperationException">if no match query operation exists on the <paramref name="context"/>.</exception>
        /// <exception cref="OperationException">if operation errors are thrown during execution of the query operation.</exception>
        public static IEnumerable Query(Type domainService, DomainServiceContext context, IList <DomainService> domainServiceInstances, string queryName, object[] parameters)
        {
            context = new DomainServiceContext(context, DomainOperationType.Query);
            DomainService            service            = CreateDomainServiceInstance(domainService, context, domainServiceInstances);
            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     queryOperation     = serviceDescription.GetQueryMethod(queryName);

            if (queryOperation == null)
            {
                string errorMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resource.DomainServiceProxy_QueryOperationNotFound,
                        queryName,
                        domainService);

                throw new InvalidOperationException(errorMessage);
            }

            object[]         parameterValues  = parameters ?? Array.Empty <object>();
            QueryDescription queryDescription = new QueryDescription(queryOperation, parameterValues);

            var actualMethod = s_queryGeneric.MakeGenericMethod(queryDescription.Method.AssociatedType);

            try
            {
                return((IEnumerable)actualMethod.Invoke(null, new object[] { service, queryDescription }));
            }
            catch (TargetInvocationException tie) when(tie.InnerException is object)
            {
                throw tie.InnerException;
            }
        }
Пример #5
0
        public async Task Authorization_Custom_Authorization_On_Query()
        {
            CityDomainService        cities             = new CityDomainService();
            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            DomainOperationEntry     getZipsIfUser      = serviceDescription.GetQueryMethod("GetZipsIfUser");

            // The attribute permits only a user named mathew to access the query
            MockUser        user        = new MockUser("NotZipGuy");
            MockDataService dataService = new MockDataService(user);

            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));

            // not authenticated should be denied cleanly because there is no user name
            Exception expectedException = null;

            System.Collections.IEnumerable result;
            try
            {
                user.IsAuthenticated = false;
                result = (await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfUser), CancellationToken.None)).Result;
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);
            Assert.AreEqual("Only one user is authorized for this query, and it isn't you.", expectedException.Message, "Expected this custom authorization deny message for non-authenticated user.");

            // Authenticated, but still not the right user name -- should be denied
            cities            = new CityDomainService();
            expectedException = null;
            user = new MockUser("NotZipGuy", new string[] { "clerk" });
            user.IsAuthenticated = true;
            dataService          = new MockDataService(user);
            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));
            try
            {
                result = (await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfUser), CancellationToken.None))
                         .Result;
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);
            Assert.AreEqual("Only one user is authorized for this query, and it isn't you.", expectedException.Message, "Expected this custom authorization deny message for authenticated user with wrong name.");

            // authenticated and in with the right name -- should be allowed
            cities = new CityDomainService();
            user   = new MockUser("ZipGuy");
            user.IsAuthenticated = true;
            dataService          = new MockDataService(user);
            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));
            var queryResult = await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfUser), CancellationToken.None);

            Assert.IsNotNull(queryResult.Result);
            Assert.IsNull(queryResult.ValidationErrors);
            Assert.IsTrue(queryResult.Result.OfType <Zip>().Any(), "Expected non-zero number of zip codes returned");
        }
Пример #6
0
        public async Task DomainService_InvalidOperationType()
        {
            TestDomainServices.EF.Northwind nw  = new TestDomainServices.EF.Northwind();
            DomainServiceContext            dsc = new DomainServiceContext(new MockDataService(new MockUser("mathew")
            {
                IsAuthenticated = true
            }), DomainOperationType.Submit);

            nw.Initialize(dsc);

            DomainServiceDescription dsd   = DomainServiceDescription.GetDescription(typeof(TestDomainServices.EF.Northwind));
            DomainOperationEntry     entry = dsd.GetQueryMethod(nameof(TestDomainServices.EF.Northwind.GetOrderDetails));
            QueryDescription         qd    = new QueryDescription(entry);
            await ExceptionHelper.ExpectExceptionAsync <InvalidOperationException>(() =>
            {
                return(nw.QueryAsync <NorthwindModel.Order_Detail>(qd, CancellationToken.None).AsTask());
            }, string.Format(Resource.DomainService_InvalidOperationType, DomainOperationType.Submit, DomainOperationType.Query));

            InvokeDescription id = new InvokeDescription(entry, null);
            await ExceptionHelper.ExpectExceptionAsync <InvalidOperationException>(() =>
            {
                return(nw.InvokeAsync(id, CancellationToken.None).AsTask());
            }, string.Format(Resource.DomainService_InvalidOperationType, DomainOperationType.Submit, DomainOperationType.Invoke));

            nw  = new TestDomainServices.EF.Northwind();
            dsc = new DomainServiceContext(new MockDataService(new MockUser("mathew")
            {
                IsAuthenticated = true
            }), DomainOperationType.Query);
            nw.Initialize(dsc);

            ChangeSet cs = new ChangeSet(new ChangeSetEntry[] {
                new ChangeSetEntry()
                {
                    Entity = new ServiceContext_CurrentOperation_Entity()
                    {
                        Key = 1
                    },
                    Operation = DomainOperation.Insert
                }
            });
            await ExceptionHelper.ExpectExceptionAsync <InvalidOperationException>(async() =>
            {
                await nw.SubmitAsync(cs, CancellationToken.None);
            }, string.Format(Resource.DomainService_InvalidOperationType, DomainOperationType.Query, DomainOperationType.Submit));
        }
Пример #7
0
        public async Task ServiceContext_CurrentOperation()
        {
            DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(ServiceContext_CurrentOperation_DomainService));
            ServiceContext_CurrentOperation_DomainService ds;

            // Execute a query.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Query);
            DomainOperationEntry queryOp = dsd.GetQueryMethod("GetEntities");

            Assert.IsNotNull(queryOp);
            QueryDescription desc = new QueryDescription(queryOp);
            var queryResult       = await ds.QueryAsync <ServiceContext_CurrentOperation_Entity>(desc, CancellationToken.None);

            Assert.AreEqual(queryOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Invoke);
            DomainOperationEntry invokeOp = dsd.GetInvokeOperation("Echo");

            Assert.IsNotNull(invokeOp);
            await ds.InvokeAsync(new InvokeDescription(invokeOp, null), CancellationToken.None);

            Assert.AreEqual(invokeOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an insert operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Submit);
            DomainOperationEntry insertOp = dsd.GetSubmitMethod(typeof(ServiceContext_CurrentOperation_Entity), DomainOperation.Insert);

            Assert.IsNotNull(insertOp);
            await ds.SubmitAsync(new ChangeSet(new ChangeSetEntry[] {
                new ChangeSetEntry()
                {
                    Entity = new ServiceContext_CurrentOperation_Entity()
                    {
                        Key = 1
                    },
                    Operation = DomainOperation.Insert
                }
            }), CancellationToken.None);

            Assert.AreEqual(insertOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);
        }
Пример #8
0
        public void ServiceContext_CurrentOperation()
        {
            DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(ServiceContext_CurrentOperation_DomainService));
            ServiceContext_CurrentOperation_DomainService ds;
            IEnumerable <ValidationResult> validationErrors;

            // Execute a query.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Query);
            DomainOperationEntry queryOp = dsd.GetQueryMethod("GetEntities");

            Assert.IsNotNull(queryOp);
            QueryDescription desc = new QueryDescription(queryOp);
            int totalCount;

            ds.Query(desc, out validationErrors, out totalCount);
            Assert.AreEqual(queryOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Invoke);
            DomainOperationEntry invokeOp = dsd.GetInvokeOperation("Echo");

            Assert.IsNotNull(invokeOp);
            ds.Invoke(new InvokeDescription(invokeOp, null), out validationErrors);
            Assert.AreEqual(invokeOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);

            // Invoke an insert operation.
            ds = new ServiceContext_CurrentOperation_DomainService(DomainOperationType.Submit);
            DomainOperationEntry insertOp = dsd.GetSubmitMethod(typeof(ServiceContext_CurrentOperation_Entity), DomainOperation.Insert);

            Assert.IsNotNull(insertOp);
            ds.Submit(new ChangeSet(new ChangeSetEntry[] {
                new ChangeSetEntry()
                {
                    Entity = new ServiceContext_CurrentOperation_Entity()
                    {
                        Key = 1
                    },
                    Operation = DomainOperation.Insert
                }
            }));
            Assert.AreEqual(insertOp, ServiceContext_CurrentOperation_DomainService.LastOperation);
            Assert.IsNull(ds.Context.Operation);
        }
Пример #9
0
        /// <summary>
        /// Helper method performs a query operation against a given proxy instance.
        /// </summary>
        /// <param name="domainService">The type of <see cref="DomainService"/> to perform this query operation against.</param>
        /// <param name="context">The current context.</param>
        /// <param name="domainServiceInstances">The list of tracked <see cref="DomainService"/> instances that any newly created
        /// <see cref="DomainServices"/> will be added to.</param>
        /// <param name="queryName">The name of the query to invoke.</param>
        /// <param name="parameters">The query parameters.</param>
        /// <returns>The query results. May be null if there are no query results.</returns>
        /// <exception cref="ArgumentNullException">if <paramref name="context"/> is null.</exception>
        /// <exception cref="ArgumentNullException">if <paramref name="queryName"/> is null or an empty string.</exception>
        /// <exception cref="InvalidOperationException">if no match query operation exists on the <paramref name="context"/>.</exception>
        /// <exception cref="OperationException">if operation errors are thrown during execution of the query operation.</exception>
        public static IEnumerable Query(Type domainService, DomainServiceContext context, IList <DomainService> domainServiceInstances, string queryName, object[] parameters)
        {
            context = new DomainServiceContext(context, DomainOperationType.Query);
            DomainService            service            = CreateDomainServiceInstance(domainService, context, domainServiceInstances);
            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(service.GetType());
            DomainOperationEntry     queryOperation     = serviceDescription.GetQueryMethod(queryName);

            if (queryOperation == null)
            {
                string errorMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resource.DomainServiceProxy_QueryOperationNotFound,
                        queryName,
                        domainService);

                throw new InvalidOperationException(errorMessage);
            }

            IEnumerable <ValidationResult> validationErrors;

            object[]         parameterValues  = parameters ?? Array.Empty <object>();
            QueryDescription queryDescription = new QueryDescription(queryOperation, parameterValues);

            // TODO: Look into removing this blocking Wait
            var actualMethod = s_queryAsync.MakeGenericMethod(queryDescription.Method.AssociatedType);
            var queryResult  = ((ValueTask <ServiceQueryResult>)actualMethod.Invoke(service, new object[] { queryDescription, CancellationToken.None }))
                               .GetAwaiter().GetResult();

            validationErrors = queryResult.ValidationErrors;
            var result = queryResult.Result;

            if (validationErrors != null && validationErrors.Any())
            {
                IEnumerable <ValidationResultInfo> operationErrors = validationErrors.Select(ve => new ValidationResultInfo(ve.ErrorMessage, ve.MemberNames));
                throw new OperationException(Resource.DomainServiceProxy_OperationError, operationErrors);
            }

            return(result);
        }
Пример #10
0
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            DomainServiceDescription description = DomainServiceDescription.GetDescription(endpoint.Contract.ContractType);

            ServiceMetadataGenerator.GenerateEntitiesMetadataJsonMap(description);

            foreach (OperationDescription od in endpoint.Contract.Operations)
            {
                foreach (IOperationBehavior behavior in od.Behaviors)
                {
                    Type behaviorType = behavior.GetType();
                    if (behaviorType.IsGenericType && behaviorType.GetGenericTypeDefinition().Equals(typeof(QueryOperationBehavior <>)))
                    {
                        IDispatchMessageFormatter innerFormatter = endpointDispatcher.DispatchRuntime.Operations[od.Name].Formatter;
                        endpointDispatcher.DispatchRuntime.Operations[od.Name].Formatter = new ServiceMetadataQueryOperationMessageFormatter(innerFormatter, DomainOperationType.Query, description.GetQueryMethod(od.Name).ReturnType);
                    }
                }
            }
        }
Пример #11
0
        public async Task Authorization_Custom_Authorization_On_Invoke()
        {
            // Specifically, the City data is marked so that no one can delete a Zip code
            // from WA unless their user name is WAGuy
            MockUser notWaGuy = new MockUser("notWAGuy");

            notWaGuy.IsAuthenticated = true;

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            DomainOperationEntry     invokeOperation    = serviceDescription.GetInvokeOperation("GetStateIfUser");

            Assert.IsNotNull(invokeOperation, "Could not locate GetStateIfUser Invoke operation");
            DomainOperationEntry getCitiesQuery = serviceDescription.GetQueryMethod("GetCities");

            City city = null;

            // Execute a query to get a City from WA
            using (CityDomainService cities = new CityDomainService())
            {
                // Now prepare for a query to find a Zip in WA
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Query);
                cities.Initialize(ctxt);

                IEnumerable result = (await cities.QueryAsync <City>(new QueryDescription(getCitiesQuery), CancellationToken.None)).Result;

                city = result.OfType <City>().FirstOrDefault(z => z.StateName == "WA");
                Assert.IsNotNull(city, "Could not find a city in WA");
            }

            // Perform an invoke against a method that has a custom auth attribute requiring WaGuy
            // where the user is something else -- should be denied
            using (CityDomainService cities = new CityDomainService())
            {
                // Prepare an invoke to call a method that has a custom auth attribute
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Invoke);
                cities.Initialize(ctxt);

                // verify that even top level exceptions go through
                // the OnError handler
                UnauthorizedAccessException expectedException = null;
                try
                {
                    // cause a domain service not initialized exception
                    await cities.InvokeAsync(new InvokeDescription(invokeOperation, new object[] { city }), CancellationToken.None);
                }
                catch (UnauthorizedAccessException e)
                {
                    expectedException = e;
                }

                Assert.IsNotNull(expectedException, "Expected Invoke to be denied");
                Assert.AreEqual("Access to operation 'GetStateIfUser' was denied.", expectedException.Message);
            }

            // Perform an invoke against a method that has a custom auth attribute requiring WaGuy
            // where the user is correct -- should be allowed
            using (CityDomainService cities = new CityDomainService())
            {
                MockUser waGuy = new MockUser("WAGuy");
                waGuy.IsAuthenticated = true;

                // Prepare an invoke to call a method that has a custom auth attribute
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(waGuy), DomainOperationType.Invoke);
                cities.Initialize(ctxt);

                // verify that even top level exceptions go through
                // the OnError handler
                UnauthorizedAccessException expectedException = null;
                try
                {
                    // cause a domain service not initialized exception
                    await cities.InvokeAsync(new InvokeDescription(invokeOperation, new object[] { city }), CancellationToken.None);
                }
                catch (UnauthorizedAccessException e)
                {
                    expectedException = e;
                }

                Assert.IsNull(expectedException, "Expected Invoke to be allowed");
            }
        }
Пример #12
0
        public async Task Authorization_MockUser()
        {
            CityDomainService        cities                 = new CityDomainService();
            DomainServiceDescription serviceDescription     = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            DomainOperationEntry     getZipsIfAuthenticated = serviceDescription.GetQueryMethod("GetZipsIfAuthenticated");
            DomainOperationEntry     getZipsIfInRole        = serviceDescription.GetQueryMethod("GetZipsIfInRole");

            // Validate a null principal is denied
            MockUser        user        = null;
            MockDataService dataService = new MockDataService(user);

            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));
            Exception expectedException = null;
            ServiceQueryResult <Zip> result;

            try
            {
                result = await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfAuthenticated), CancellationToken.None);
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);

            Assert.AreEqual("Access to operation 'GetZipsIfAuthenticated' was denied.", expectedException.Message, "Expected standard deny message for null principal");

            // Validate a non-authenticated user is denied
            user        = new MockUser("mathew");
            dataService = new MockDataService(user);
            cities      = new CityDomainService();
            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));

            expectedException = null;
            try
            {
                user.IsAuthenticated = false;
                result = await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfAuthenticated), CancellationToken.None);
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);

            // we're authenticated, so this should succeed
            expectedException    = null;
            user.IsAuthenticated = true;
            result = await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfAuthenticated), CancellationToken.None);

            Assert.IsNotNull(result.Result);

            // authenticated, but not in role, so we should fail
            cities            = new CityDomainService();
            expectedException = null;
            user = new MockUser("mathew", new string[] { "clerk" });
            user.IsAuthenticated = true;
            dataService          = new MockDataService(user);
            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));
            try
            {
                result = await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfInRole), CancellationToken.None);
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);

            // authenticated and in role, so we should succeed
            cities = new CityDomainService();
            user   = new MockUser("mathew", new string[] { "manager" });
            user.IsAuthenticated = true;
            dataService          = new MockDataService(user);
            cities.Initialize(new WcfDomainServiceContext(dataService, DomainOperationType.Query));
            result = await cities.QueryAsync <Zip>(new QueryDescription(getZipsIfInRole), CancellationToken.None);

            Assert.IsNotNull(result);
        }
Пример #13
0
        public async Task Authorization_Custom_Authorization_On_Custom_Update()
        {
            // Specifically, the City data is marked so that no one can delete a Zip code
            // from WA unless their user name is WAGuy
            MockUser notWaGuy = new MockUser("notWAGuy");

            notWaGuy.IsAuthenticated = true;

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            City city = null;

            // Execute a query to get a City from WA
            using (CityDomainService cities = new CityDomainService())
            {
                DomainOperationEntry getCitiesQuery = serviceDescription.GetQueryMethod("GetCities");

                // Now prepare for a query to find a Zip in WA
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Query);
                cities.Initialize(ctxt);

                IEnumerable result = (await cities.QueryAsync <City>(new QueryDescription(getCitiesQuery), CancellationToken.None)).Result;

                city = result.OfType <City>().FirstOrDefault(z => z.StateName == "WA");
                Assert.IsNotNull(city, "Could not find a city in WA");
            }


            using (CityDomainService cities = new CityDomainService())
            {
                // Now prepare for a submit to invoke AssignCityZoneIfAuthorized as a named update method
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Submit);
                cities.Initialize(ctxt);

                // Prepare an attempt to delete this with a user whose name is not WAGuy
                // This should fail due to a custom auth attribute
                List <ChangeSetEntry> entries = new List <ChangeSetEntry>();

                ChangeSetEntry entry = new ChangeSetEntry();
                entry.DomainOperationEntry = serviceDescription.GetCustomMethod(typeof(City), "AssignCityZoneIfAuthorized");
                entry.EntityActions        = new EntityActionCollection {
                    { "AssignCityZoneIfAuthorized", new object[] { "SomeZone" } }
                };
                entry.Operation = DomainOperation.Update;
                entry.Entity    = city;
                entries.Add(entry);

                UnauthorizedAccessException exception = null;
                try
                {
                    await ChangeSetProcessor.ProcessAsync(cities, entries);
                }
                catch (UnauthorizedAccessException ex)
                {
                    exception = ex;
                }
                Assert.IsNotNull(exception, "Expected failure attempting to perform custom method on WA with inappropriate user name");
                Assert.AreEqual("Only one user is authorized to execute operation 'AssignCityZoneIfAuthorized', and it isn't you.", exception.Message);
            }

            // Now do that again but with a user who is WAGuy -- it should succeed
            using (CityDomainService cities = new CityDomainService())
            {
                MockUser waGuy = new MockUser("WAGuy");
                waGuy.IsAuthenticated = true;

                // Now prepare for a submit to invoke AssignCityZoneIfAuthorized as a named update method
                DomainServiceContext ctxt = new WcfDomainServiceContext(new MockDataService(waGuy), DomainOperationType.Submit);
                cities.Initialize(ctxt);

                // Prepare an attempt to delete this with a user whose name is not WAGuy
                // This should fail due to a custom auth attribute

                // Prepare a submit to call the AssignCityZoneIfAuthorized with an unauthorized user
                List <ChangeSetEntry> entries = new List <ChangeSetEntry>();

                ChangeSetEntry entry = new ChangeSetEntry();
                entry.DomainOperationEntry = serviceDescription.GetCustomMethod(typeof(City), "AssignCityZoneIfAuthorized");
                entry.EntityActions        = new EntityActionCollection {
                    { "AssignCityZoneIfAuthorized", new object[] { "SomeZone" } }
                };
                entry.Operation = DomainOperation.Update;
                entry.Entity    = city;
                entries.Add(entry);

                Exception exception = null;
                try
                {
                    await ChangeSetProcessor.ProcessAsync(cities, entries);
                }
                catch (UnauthorizedAccessException ex)
                {
                    exception = ex;
                }
                Assert.IsNull(exception, "Expected success attempting to delete a zip from WA with inappropriate user name");
            }
        }
Пример #14
0
        public async Task Authorization_Custom_Authorization_On_CUD()
        {
            // Specifically, the City data is marked so that no one can delete a Zip code
            // from WA unless their user name is WAGuy
            MockUser notWaGuy = new MockUser("notWAGuy");

            notWaGuy.IsAuthenticated = true;

            DomainServiceDescription serviceDescription = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            Zip zip = null;

            // First execute a query to get some zips
            DomainOperationEntry getZipsQuery = serviceDescription.GetQueryMethod("GetZips");
            DomainServiceContext ctxt;

            using (CityDomainService cities = new CityDomainService())
            {
                // Now prepare for a query to find a Zip in WA
                ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Query);
                cities.Initialize(ctxt);
                IEnumerable result = (await cities.QueryAsync <Zip>(new QueryDescription(getZipsQuery), CancellationToken.None)).Result;

                zip = result.OfType <Zip>().FirstOrDefault(z => z.StateName == "WA");
                Assert.IsNotNull(zip, "Could not find a zip code in WA");
            }

            // Prepare a submit to delete this zip from a user who is not authorized
            using (CityDomainService cities = new CityDomainService())
            {
                // Now prepare for a query to find a Zip in WA
                ctxt = new WcfDomainServiceContext(new MockDataService(notWaGuy), DomainOperationType.Submit);
                cities.Initialize(ctxt);

                // Prepare an attempt to delete this with a user whose name is not WAGuy
                // This should fail due to a custom auth attribute
                List <ChangeSetEntry> entries = new List <ChangeSetEntry>();

                ChangeSetEntry entry = new ChangeSetEntry(1, zip, zip, DomainOperation.Delete);
                entries.Add(entry);
                UnauthorizedAccessException exception = null;
                try
                {
                    await ChangeSetProcessor.ProcessAsync(cities, entries);
                }
                catch (UnauthorizedAccessException ex)
                {
                    exception = ex;
                }
                Assert.IsNotNull(exception, "Expected failure attempting to delete a zip from WA with inappropriate user name");
                Assert.AreEqual("Only one user can delete zip codes from that state, and it isn't you.", exception.Message);
            }

            // Now do that again but with a user who is WAGuy -- it should succeed
            using (CityDomainService cities = new CityDomainService())
            {
                MockUser waGuy = new MockUser("WAGuy");
                waGuy.IsAuthenticated = true;

                // Now try a submit where the user *is* Mathew to validate we succeed
                ctxt = new WcfDomainServiceContext(new MockDataService(waGuy), DomainOperationType.Submit);
                cities.Initialize(ctxt);
                List <ChangeSetEntry> entries = new List <ChangeSetEntry>();

                ChangeSetEntry entry = new ChangeSetEntry(1, zip, zip, DomainOperation.Delete);
                entries.Add(entry);
                Exception exception = null;
                try
                {
                    await ChangeSetProcessor.ProcessAsync(cities, entries);
                }
                catch (UnauthorizedAccessException ex)
                {
                    exception = ex;
                }
                Assert.IsNull(exception, "Expected success attempting to delete a zip from WA with inappropriate user name");
            }
        }
Пример #15
0
        public void Authorization_MockUser()
        {
            int count;
            CityDomainService        cities                 = new CityDomainService();
            DomainServiceDescription serviceDescription     = DomainServiceDescription.GetDescription(typeof(CityDomainService));
            DomainOperationEntry     getZipsIfAuthenticated = serviceDescription.GetQueryMethod("GetZipsIfAuthenticated");
            DomainOperationEntry     getZipsIfInRole        = serviceDescription.GetQueryMethod("GetZipsIfInRole");

            // Validate a null principal is denied
            MockUser        user        = null;
            MockDataService dataService = new MockDataService(user);

            cities.Initialize(new DomainServiceContext(dataService, DomainOperationType.Query));
            Exception expectedException = null;

            System.Collections.IEnumerable result;
            IEnumerable <ValidationResult> validationErrors = null;

            try
            {
                result = cities.Query(new QueryDescription(getZipsIfAuthenticated), out validationErrors, out count);
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);
            Assert.IsNull(validationErrors);
            Assert.AreEqual("Access to operation 'GetZipsIfAuthenticated' was denied.", expectedException.Message, "Expected standard deny message for null principal");

            // Validate a non-authenticated user is denied
            user        = new MockUser("mathew");
            dataService = new MockDataService(user);
            cities      = new CityDomainService();
            cities.Initialize(new DomainServiceContext(dataService, DomainOperationType.Query));

            expectedException = null;
            validationErrors  = null;
            try
            {
                user.IsAuthenticated = false;
                result = cities.Query(new QueryDescription(getZipsIfAuthenticated), out validationErrors, out count);
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);
            Assert.IsNull(validationErrors);

            // we're authenticated, so this should succeed
            expectedException    = null;
            user.IsAuthenticated = true;
            result = cities.Query(new QueryDescription(getZipsIfAuthenticated), out validationErrors, out count);
            Assert.IsNotNull(result);
            Assert.IsNull(validationErrors);

            // authenticated, but not in role, so we should fail
            cities            = new CityDomainService();
            expectedException = null;
            user = new MockUser("mathew", new string[] { "clerk" });
            user.IsAuthenticated = true;
            dataService          = new MockDataService(user);
            cities.Initialize(new DomainServiceContext(dataService, DomainOperationType.Query));
            try
            {
                result = cities.Query(new QueryDescription(getZipsIfInRole), out validationErrors, out count);
            }
            catch (UnauthorizedAccessException e)
            {
                expectedException = e;
            }
            Assert.IsNotNull(expectedException);
            Assert.IsNull(validationErrors);

            // authenticated and in role, so we should succeed
            cities            = new CityDomainService();
            expectedException = null;
            user = new MockUser("mathew", new string[] { "manager" });
            user.IsAuthenticated = true;
            dataService          = new MockDataService(user);
            cities.Initialize(new DomainServiceContext(dataService, DomainOperationType.Query));
            result = cities.Query(new QueryDescription(getZipsIfInRole), out validationErrors, out count);
            Assert.IsNotNull(result);
            Assert.IsNull(validationErrors);
        }