Example #1
0
        public HttpResponseMessageWrapper <Item> UpdateItem(HttpRequestMessage req, Guid id)
        {
            Operation      operation = null;
            HttpStatusCode code      = AuthenticateUser(req);

            if (code != HttpStatusCode.OK)
            {   // user not authenticated
                return(ReturnResult <Item>(req, operation, code));
            }

            List <Item> clientItems = null;

            code = ProcessRequestBody <List <Item> >(req, out clientItems, out operation);
            if (code != HttpStatusCode.OK)  // error encountered processing body
            {
                return(ReturnResult <Item>(req, operation, code));
            }

            Item originalItem = clientItems[0];
            Item newItem      = clientItems[1];

            // make sure the item ID's match
            if (originalItem.ID != id || newItem.ID != id)
            {
                TraceLog.TraceError("ID in URL does not match entity body");
                return(ReturnResult <Item>(req, operation, HttpStatusCode.BadRequest));
            }

            // if parent ID is an empty guid, make it null instead so as to not violate ref integrity rules
            if (originalItem.ParentID == Guid.Empty)
            {
                originalItem.ParentID = null;
            }
            if (newItem.ParentID == Guid.Empty)
            {
                newItem.ParentID = null;
            }

            if (newItem.LastModified.Year == 1970)
            {   // web client sets Date(0) to get server timestamp (ticks since 1970)
                newItem.LastModified = DateTime.UtcNow;
            }

            // get the folder for the item
            try
            {
                Item requestedItem = this.StorageContext.Items.Include("ItemTags").Include("FieldValues").Single <Item>(t => t.ID == id);

                // if the Folder does not belong to the authenticated user, return 403 Forbidden
                if (requestedItem.UserID != CurrentUser.ID)
                {
                    TraceLog.TraceError("Entity does not belong to current user)");
                    return(ReturnResult <Item>(req, operation, HttpStatusCode.Forbidden));
                }
                // reset the UserID fields to the appropriate user, to ensure update is done in the context of the current user
                originalItem.UserID = requestedItem.UserID;
                newItem.UserID      = requestedItem.UserID;

                Folder originalFolder = this.StorageContext.Folders.Single <Folder>(tl => tl.ID == originalItem.FolderID);
                Folder newFolder      = this.StorageContext.Folders.Single <Folder>(tl => tl.ID == newItem.FolderID);

                if (originalFolder.UserID != CurrentUser.ID || newFolder.UserID != CurrentUser.ID ||
                    originalItem.UserID != CurrentUser.ID || newItem.UserID != CurrentUser.ID)
                {   // folder or item does not belong to the authenticated user, return 403 Forbidden
                    TraceLog.TraceError("Folder of Entity does not belong to current user)");
                    return(ReturnResult <Item>(req, operation, HttpStatusCode.Forbidden));
                }

                try
                {
                    bool changed = false;

                    if (requestedItem.ItemTags != null && requestedItem.ItemTags.Count > 0)
                    {   // delete all the itemtags associated with this item
                        foreach (var tt in requestedItem.ItemTags.ToList())
                        {
                            this.StorageContext.ItemTags.Remove(tt);
                        }
                        changed = true;
                    }

                    ItemProcessor ip = ItemProcessor.Create(CurrentUser, StorageContext, newItem.ItemTypeID);
                    if (ip != null)
                    {   // do itemtype-specific processing
                        ip.ProcessUpdate(originalItem, newItem);
                    }

                    // call update and make sure the changed flag reflects the outcome correctly
                    changed = (Update(requestedItem, originalItem, newItem) == true ? true : changed);
                    if (changed == true)
                    {
                        int rows = this.StorageContext.SaveChanges();
                        if (rows < 0)
                        {
                            TraceLog.TraceError("Internal Server Error (database operation did not succeed)");
                            return(ReturnResult <Item>(req, operation, HttpStatusCode.InternalServerError));
                        }
                        else
                        {
                            if (rows == 0)
                            {
                                TraceLog.TraceInfo("Inconsistency between the results of Update and zero rows affected");
                            }
                            if (newFolder.Name.StartsWith("$") == false)
                            {
                                WorkflowHost.WorkflowHost.InvokeWorkflowForOperation(this.StorageContext, null, operation);
                            }
                            TraceLog.TraceInfo("Accepted");
                            return(ReturnResult <Item>(req, operation, requestedItem, HttpStatusCode.Accepted));
                        }
                    }
                    else
                    {
                        TraceLog.TraceInfo("Accepted (no changes)");
                        return(ReturnResult <Item>(req, operation, requestedItem, HttpStatusCode.Accepted));
                    }
                }
                catch (Exception ex)
                {   // item not found - return 404 Not Found
                    TraceLog.TraceException("Resource not found (Item)", ex);
                    return(ReturnResult <Item>(req, operation, HttpStatusCode.NotFound));
                }
            }
            catch (Exception ex)
            {   // folder not found - return 404 Not Found
                TraceLog.TraceException("Resource not found (Folder)", ex);
                return(ReturnResult <Item>(req, operation, HttpStatusCode.NotFound));
            }
        }