コード例 #1
0
 /// <summary>
 /// The add filters to debug if required.
 /// </summary>
 /// <param name="context">
 /// The context.
 /// </param>
 private static void AddFiltersToDebugIfRequired(ITestApiContext context)
 {
     if (context.NeedsDebugInformation())
     {
         context.Debug.Filters = context.Filters;
     }
 }
コード例 #2
0
        /// <summary>
        ///     Builds the resources for.
        /// </summary>
        /// <param name="context">Context containing information about the request.</param>
        /// <returns>
        ///     <see cref="JsonHomeDocument" /> populated according to current user's permissions.
        /// </returns>
        public JsonHomeDocument BuildResourcesFor(ITestApiContext context)
        {
            var jsonHomeDocument = new JsonHomeDocument();

            foreach (var function in Functions)
            {
                var functionName  = function.Key;
                var functionValue = function.Value;
                var webFunction   = new WebFunction(
                    functionValue.Href,
                    functionValue.Relation,
                    functionValue.Templated,
                    CreateHints(functionName, "Active", DetermineAvailableVerbs(functionName, context), null),
                    ulong.MaxValue);

                var listOfHints =
                    (IEnumerable <HttpVerb>)webFunction.Hints.FirstOrDefault(x => x.Key.Contains("allow")).Value;

                if (webFunction.RequiredPermissions > 0 && listOfHints.Any())
                {
                    jsonHomeDocument.AddFunction(functionName, webFunction);
                }
            }

            return(jsonHomeDocument);
        }
コード例 #3
0
        private static IDebugInformation ExcludeDebugInformation(ITestApiContext testApiContext)
        {
            if (!testApiContext.NeedsDebugInformation())
            {
                return(null);
            }

            if (testApiContext.DebugLevel == DebugLevel.InternalQueryOnly)
            {
                return(new DebugInformation {
                    Filters = testApiContext.Debug.Filters
                });
            }

            if (testApiContext.DebugLevel == DebugLevel.TimingsOnly)
            {
                var debug = new DebugInformation();

                testApiContext.Debug.Timings.ForEach(debug.AddTimingEvent);

                return(debug);
            }

            return(testApiContext.Debug);
        }
コード例 #4
0
        /// <summary>
        /// The build.
        /// </summary>
        /// <param name="request">
        /// The request.
        /// </param>
        /// <param name="responseBuilder">
        /// The response builder.
        /// </param>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <typeparam name="T">
        /// </typeparam>
        /// <returns>
        /// The <see cref="HttpResponseMessage"/>.
        /// </returns>
        public HttpResponseMessage Build <T>(
            HttpRequestMessage request,
            Func <ResponseEnvelope <T> > responseBuilder,
            ITestApiContext context)
        {
            try
            {
                var response = responseBuilder.Invoke();

                var httpResponse = request.CreateResponse(HttpStatusCode.OK, response);

                response.Meta.AddMetaDataInformation("elapsedTimeInMS", context.ElapsedTimeInMS);

                AddETag(httpResponse, (dynamic)response.Payload, response.ApiVersion);

                return(httpResponse);
            }
            catch (ArgumentNullException ex)
            {
                return(request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
            catch (Exception ex)
            {
                return(request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex));
            }
        }
コード例 #5
0
        private void Add(ITestApiContext context)
        {
            Ticket ticket = new Ticket();

            ticket.ID      = Guid.NewGuid();
            ticket.Subject = "my";
            ticket.UserID  = context.AuthenticatedUser.Id.ToGuid();
            _ticketService.AddTicket(ticket);
        }
コード例 #6
0
        public ResponseEnvelope <Guid> HandleDelete(Guid id, ITestApiContext context)
        {
            _ticketService.DeleteTicket(id);

            var recordCounts = CreateRecordCounts(1);

            var searchResults = new ApiSearchResult <Guid>(recordCounts, id);

            return(_responseBuilder.CreateResponse(context, searchResults));
        }
コード例 #7
0
        /// <summary>
        /// The create details.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="record">
        /// The record.
        /// </param>
        /// <typeparam name="TIn">
        /// </typeparam>
        /// <typeparam name="TOut">
        /// </typeparam>
        /// <returns>
        /// The <see cref="TOut"/>.
        /// </returns>
        public TOut CreateDetails <TIn, TOut>(ITestApiContext context, ApiResourceEndPoint endPoint, IApiSearchResult <TIn> record)
        //// This constraint is to ensure the object being created is an IWebLinkable.  The reason for the
        //// generic is to use in _objectFactory.Create
            where TOut : IWebLinkable
        {
            var recordDetail = this._objectFactory.Create <TOut>(record.Results);

            AppendFunctionsTo(new[] { recordDetail }, endPoint, context);

            return(recordDetail);
        }
コード例 #8
0
        public ResponseEnvelope <UserWM> HandleCurrentUserGet(ITestApiContext context)
        {
            var user = _userService.GetUser(context.AuthenticatedUser.Id.ToGuid());

            var usersWM = _objectFactory.Create <UserWM>(user);

            var recordCounts = CreateRecordCounts(1);

            var searchResults = new ApiSearchResult <UserWM>(recordCounts, usersWM);

            var response = _responseBuilder.CreateResponse(context, searchResults);

            return(response);
        }
コード例 #9
0
        /// <summary>
        /// Create the response from the request context and the record.
        /// </summary>
        /// <param name="context">
        /// Context containing information about the request.
        /// </param>
        /// <param name="results">
        /// The data record for the request.
        /// </param>
        /// <typeparam name="T">
        /// The type of object that is being returned from the request.
        /// </typeparam>
        /// <returns>
        /// The <see cref="ResponseEnvelope{T}"/> describing the data for the request.
        /// </returns>
        public ResponseEnvelope <T> CreateResponse <T>(ITestApiContext context, IApiSearchResult <T> results)
        {
            var response = new ResponseEnvelope <T>
            {
                Meta        = context.MetaData,
                Payload     = results.Results,
                RecordCount = CreateRecordCounts(results.RecordCounts),
                Debug       = ExcludeDebugInformation(context),
                Warnings    = context.Warnings.IsNullOrEmpty() ? null : context.Warnings,
                Errors      = context.Errors.IsNullOrEmpty() ? null : context.Errors
            };

            return(response);
        }
コード例 #10
0
        /// <summary>
        /// The create details.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <param name="results">
        /// The results.
        /// </param>
        /// <typeparam name="TIn">
        /// </typeparam>
        /// <typeparam name="TOut">
        /// </typeparam>
        /// <returns>
        /// A IEnumerable containing all the results translated.
        /// </returns>
        public IEnumerable <TOut> CreateDetails <TIn, TOut>(
            ITestApiContext context,
            ApiResourceEndPoint endPoint,
            IApiSearchResult <IEnumerable <TIn> > results)
        //// This constraint is to ensure the object being created is an IWebLinkable.  The reason for the
        //// generic is to use in _objectFactory.Create
            where TOut : IWebLinkable
        {
            var recordDetails = context.TimeIt("Transform To Response Type", () => results
                                               .Results
                                               .Select(record => this._objectFactory.Create <TOut>(record))).ToList();

            context.TimeIt("Append Functions", () => AppendFunctionsTo(recordDetails, endPoint, context));

            return(recordDetails);
        }
コード例 #11
0
        /// <summary>
        /// The handle get.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// The <see cref="ResponseEnvelope"/>.
        /// </returns>
        public ResponseEnvelope <IEnumerable <UserWM> > HandleGet(ITestApiContext context)
        {
            var results = _unitOfWork.GetRepository <UserEntity>().All();

            var users = results.Select(userEntity => _objectFactory.Create <User>(userEntity));

            var usersWM = users.Select(user => _objectFactory.Create <UserWM>(user));

            var recordCounts = CreateRecordCounts(usersWM.Count());

            var searchResults = new ApiSearchResult <IEnumerable <UserWM> >(recordCounts, usersWM);


            var response = _responseBuilder.CreateResponse(context, searchResults);

            return(response);
        }
コード例 #12
0
        public ResponseEnvelope <TicketWM> HandlePut(Guid id, TicketWM ticketWM, ITestApiContext context)
        {
            var ticket = _objectFactory.Create <Ticket>(ticketWM);

            _ticketService.UpdateTicket(ticket);

            var updatedTicket = _ticketService.GetTicket(id);


            var ticketWMUpadted = _objectFactory.Create <TicketWM>(updatedTicket);

            var recordCounts = CreateRecordCounts(1);

            var searchResults = new ApiSearchResult <TicketWM>(recordCounts, ticketWMUpadted);

            return(_responseBuilder.CreateResponse(context, searchResults));
        }
コード例 #13
0
        private T CreatePathFromOperation <T>(PatchOperation operation, ITestApiContext context) where T : PatchOperationBase
        {
            var validationResult = this._pathFromValidationService.Validate(operation);

            if (validationResult.HasErrors())
            {
                context.AddError(string.Format("{0}  The instruction was ignored.", validationResult));
                return(null);
            }

            if (operation.Value != null)
            {
                context.AddWarning(FormatTooMuchInformationWarningMessage(operation, "value"));
            }

            return(this.CreateOperation <T>(operation.Path, operation.From));
        }
コード例 #14
0
        /// <summary>
        /// The handle get.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// The <see cref="ResponseEnvelope"/>.
        /// </returns>
        public ResponseEnvelope <IEnumerable <TicketWM> > HandleGet(ITestApiContext context)
        {
            var results = _ticketService.GetAllTickets(context.AuthenticatedUser.Id.ToGuid()).ToList();

            var apiSearchResult = new ApiSearchResult <IEnumerable <Ticket> >(CreateRecordCounts(results.Count()), results);

            var ticketWMList = _responseBuilder.CreateDetails <Ticket, TicketWM>(context, ApiResourceEndPointForThisHandler, apiSearchResult);


            //   var ticketWMList = results.Select(ticket => _objectFactory.Create<TicketWM>(ticket));


            var recordCounts = CreateRecordCounts(ticketWMList.Count());

            var searchResults = new ApiSearchResult <IEnumerable <TicketWM> >(recordCounts, ticketWMList);

            return(_responseBuilder.CreateResponse(context, searchResults));
        }
コード例 #15
0
        private T CreatePathValueOperation <T>(PatchOperation operation, ITestApiContext context) where T : PatchOperationBase
        {
            var validationResult = this._pathValueValidationService.Validate(operation);

            if (validationResult.HasErrors())
            {
                context.AddError(string.Format("{0}  The instruction was ignored.", validationResult));
                return(null);
            }

            if (!operation.From.IsNullOrEmpty())
            {
                var warning = FormatTooMuchInformationWarningMessage(operation, "from");
                context.AddWarning(warning);
            }

            return(this.CreateOperation <T>(operation.Path, operation.Value));
        }
コード例 #16
0
        public ResponseEnvelope <TicketWM> HandlePost(ITestApiContext context, TicketWM ticketWM)
        {
            var ticket = _objectFactory.Create <Ticket>(ticketWM);

            ticket.ID     = Guid.NewGuid();
            ticket.UserID = context.AuthenticatedUser.Id;
            _ticketService.AddTicket(ticket);

            var addedTicket = _ticketService.GetTicket(ticket.ID);


            var ticketWMAdded = _objectFactory.Create <TicketWM>(ticket);

            var recordCounts = CreateRecordCounts(1);

            var searchResults = new ApiSearchResult <TicketWM>(recordCounts, ticketWMAdded);

            return(_responseBuilder.CreateResponse(context, searchResults));
        }
コード例 #17
0
 /// <summary>
 /// The populate meta data.
 /// </summary>
 /// <param name="metaData">
 /// The meta data.
 /// </param>
 /// <param name="context">
 /// The context.
 /// </param>
 /// <param name="filters">
 /// The filters.
 /// </param>
 private static void PopulateMetaData(IMetaDataEnvelope metaData, ITestApiContext context, string filters)
 {
     metaData.AddMetaDataInformation("count", context.Count);
     metaData.AddMetaDataInformation("offset", context.Offset);
     metaData.AddMetaDataInformation("filters", filters);
 }
コード例 #18
0
 /// <summary>
 /// Apply the changes in <paramref name="operations"/> to <paramref name="entity"/>.
 /// </summary>
 /// <param name="entity">
 /// The object to apply the operations too.
 /// </param>
 /// <param name="operations">
 /// A list of operations that was passed in with the PATCH request.
 /// </param>
 /// <param name="context">
 /// Context containing information about the request.
 /// </param>
 public void Patch(object entity, IEnumerable <PatchOperationBase> operations, ITestApiContext context)
 {
     foreach (dynamic operation in operations)
     {
         ApplyOperation(entity, operation, context);
     }
 }
コード例 #19
0
        /// <summary>
        /// The translate.
        /// </summary>
        /// <param name="operations">
        /// The operations.
        /// </param>
        /// <param name="context">
        /// Context containing information about the request.
        /// </param>
        /// <returns>
        /// The patch operations in business object form.
        /// </returns>
        public IEnumerable <PatchOperationBase> Translate(IEnumerable <PatchOperation> operations, ITestApiContext context)
        {
            Ensure.That <PostRequestEntityDetailsNullException>(operations != null);

            var operationList = new List <PatchOperationBase>();

            foreach (var operation in operations)
            {
                var operationInstruction = operation.Operation ?? string.Empty;
                switch (operationInstruction.ToLowerInvariant())
                {
                case "test":
                    var testOperation = this.CreatePathValueOperation <TestPatchOperation>(operation, context);
                    if (testOperation != null)
                    {
                        operationList.Add(testOperation);
                    }

                    break;

                case "remove":
                    var removeOperation = this.CreatePathOnlyOperation <RemovePatchOperation>(operation, context);
                    if (removeOperation != null)
                    {
                        operationList.Add(removeOperation);
                    }

                    break;

                case "add":
                    var addOperation = this.CreatePathValueOperation <AddPatchOperation>(operation, context);
                    if (addOperation != null)
                    {
                        operationList.Add(addOperation);
                    }

                    break;

                case "replace":
                    var replaceOperation = this.CreatePathValueOperation <ReplacePatchOperation>(operation, context);
                    if (replaceOperation != null)
                    {
                        operationList.Add(replaceOperation);
                    }

                    break;

                case "move":
                    var moveOperation = this.CreatePathFromOperation <MovePatchOperation>(operation, context);
                    if (moveOperation != null)
                    {
                        operationList.Add(moveOperation);
                    }

                    break;

                case "copy":
                    var copyOperation = this.CreatePathFromOperation <CopyPatchOperation>(operation, context);
                    if (copyOperation != null)
                    {
                        operationList.Add(copyOperation);
                    }

                    break;

                default:
                    context.AddError(string.Format(@"Invalid PATCH operation '{0}'.  The instruction was ignored.", operation.Operation ?? "null"));
                    break;
                }
            }

            return(operationList);
        }
コード例 #20
0
        public ResponseEnvelope <TicketWM> HandlePatch(Guid entityId, IEnumerable <PatchOperationBase> changes, ITestApiContext context)
        {
            var ticketEntity = _ticketService.GetTicket(entityId);

            var ticket = _objectFactory.Create <Ticket>(ticketEntity);

            var ticketWM = _objectFactory.Create <TicketWM>(ticket);


            var operationBases = changes as IList <PatchOperationBase> ?? changes.ToList();

            //Todo This logic will be changed when rest of PatchOperation will be decided.
            var replaceOperatonList =
                operationBases.Where(operation => operation.GetType() == typeof(ReplacePatchOperation)).ToList();

            var invalidOperations = replaceOperatonList.Where(x => x.Path.TrimStart('/').Equals("ticketNumber", StringComparison.OrdinalIgnoreCase));

            if (invalidOperations.Any())
            {
                context.AddError("Invalid patch request.");
                throw new BadRequestException();
            }

            _entityPatcher.Patch(ticketWM, replaceOperatonList, context);


            _ticketService.UpdateTicket(_objectFactory.Create <Ticket>(ticketWM));


            var updatedTicket = _ticketService.GetTicket(entityId);


            var ticketWMUpadted = _objectFactory.Create <TicketWM>(updatedTicket);

            var recordCounts = CreateRecordCounts(1);

            var searchResults = new ApiSearchResult <TicketWM>(recordCounts, ticketWMUpadted);

            return(_responseBuilder.CreateResponse(context, searchResults));
        }
コード例 #21
0
 private static void ApplyOperation <T>(T entity, CopyPatchOperation operation, ITestApiContext context)
 {
     var path = new Queue <string>(operation.Path.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries));
 }
コード例 #22
0
        public void AppendLinksTo(IWebLinkable webLinkable, ApiResourceEndPoint endPoint, ITestApiContext context)
        {
            var weblinkType = webLinkable.GetType();

            if (!_linkCreators.ContainsKey(webLinkable.GetType()))
            {
                return;
            }

            _linkCreators[weblinkType].AppendFunctionsTo(webLinkable, endPoint, context);
        }
コード例 #23
0
        private static void ApplyOperation <T>(T entity, RemovePatchOperation operation, ITestApiContext context)
        {
            var path = new Queue <string>(operation.Path.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries));

            UpdateField(entity, path, default(T), context);
        }
コード例 #24
0
        private static void UpdateField(object entity, Queue <string> path, object value, ITestApiContext context)
        {
            var entityType   = entity.GetType();
            var propertyName = path.Dequeue();

            var property = entityType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

            if (property == null)
            {
                context.AddError(
                    string.Format("Property Name {0} does not exist in {1} Model", propertyName, entityType.Name));
                return;
            }

            if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(IDictionary <,>))
            {
                var dictionary = GetDictionaryPropertyValue(entity, path, value, property);
                value = dictionary;
            }

            value = GetCollectionPropertyValue(value, property);

            if (path.Any())
            {
                var propertyValue = property.GetValue(entity);

                UpdateField(propertyValue, path, value, context);
                return;
            }

            var strongTypedValue =
                value is IConvertible
                   ? Convert.ChangeType(value, property.PropertyType)
                   : value;

            property.SetValue(entity, strongTypedValue);
        }
コード例 #25
0
 /// <summary>
 /// Gets the specified user.
 /// </summary>
 /// <param name="TestContext">The request context.</param>
 /// <returns>
 /// Fully built <see cref="JsonHomeDocument"/>.
 /// </returns>
 public JsonHomeDocument HandleGet(ITestApiContext testApiContext)
 {
     return(this._builder.BuildResourcesFor(testApiContext));
 }
コード例 #26
0
 private void AppendFunctionsTo <T>(IEnumerable <T> webLinkable, ApiResourceEndPoint endPoint, ITestApiContext context)
     where T : IWebLinkable
 {
     webLinkable.ForEach(linkable => this._functionAppender.AppendLinksTo(linkable, endPoint, context));
 }
コード例 #27
0
        /// <summary>
        /// Appends the links to.
        /// </summary>
        /// <param name="webLinkable">The <see cref="IWebLinkable" /> object.</param>
        /// <param name="endPoint"></param>
        /// <param name="context">Context containing information about the request.</param>
        //public void AppendFunctionsTo(IWebLinkable webLinkable, ApiResourceEndPoint endPoint, ITestApiContext context)
        //{
        //    var webLinkableType = webLinkable.GetType();
        //    if (webLinkableType != CreatesLinksFor)
        //    {
        //        context.AddWarning(
        //            string.Format(
        //                @"Trying to add functions to invalid type {0} in LightboxDetailFunctionAppender.  Operation Cancelled",
        //                webLinkableType));
        //        return;
        //    }

        //    var securableObjectPermission =
        //        context.AuthenticatedUser.Permissions.FirstOrDefault(
        //            p => p.SecurableObjectType.Equals(SecurableObjectType.OrgUnit));

        //    webLinkable.Links.Self = "lightbox";

        //    if (securableObjectPermission == null)
        //    {
        //        AddFunctionsToWebLinkable(
        //            f => f.Value.ResourceEndPoints.Contains(endPoint) && f.Value.Permissions == ulong.MaxValue,
        //            webLinkable.Links);

        //        return;
        //    }

        //    AddFunctionsToWebLinkable(
        //        f => f.Value.ResourceEndPoints.Contains(endPoint) && (f.Value.Permissions & securableObjectPermission.Permissions) > 0 || f.Value.Permissions == ulong.MaxValue,
        //        webLinkable.Links);
        //}


        public void AppendFunctionsTo(IWebLinkable webLinkable, ApiResourceEndPoint endPoint, ITestApiContext context)
        {
            var webLinkableType = webLinkable.GetType();

            if (webLinkableType != CreatesLinksFor)
            {
                context.AddWarning(
                    string.Format(
                        @"Trying to add functions to invalid type {0} in LightboxDetailFunctionAppender.  Operation Cancelled",
                        webLinkableType));
                return;
            }

            webLinkable.Links.Self = "tickets";

            AddFunctionsToWebLinkable(
                f => f.Value.ResourceEndPoints.Contains(endPoint) && f.Value.Permissions == ulong.MaxValue,
                webLinkable.Links);
        }
コード例 #28
0
        private static IEnumerable <HttpVerb> DetermineAvailableVerbs(string function, ITestApiContext context)
        {
            if (!VerbMapping.ContainsKey(function))
            {
                return(Enumerable.Empty <HttpVerb>());
            }

            var securableObjectPermission =
                context.AuthenticatedUser.Permissions.FirstOrDefault(
                    p => p.SecurableObjectType.Equals(SecurableObjectType.Organization));

            if (securableObjectPermission == null)
            {
                return(Enumerable.Empty <HttpVerb>());
            }

            return
                (VerbMapping[function].Where(
                     mapping =>
                     mapping.Value == ulong.MaxValue || ((mapping.Value & securableObjectPermission.Permissions) > 0))
                 .Select(mapping => mapping.Key));
        }