Ejemplo n.º 1
0
        public HttpResponseMessageWrapper <Item> DeleteItem(HttpRequestMessage req, Guid id)
        {
            Operation      operation = null;
            HttpStatusCode code      = AuthenticateUser(req);

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

            // get the item from the message body if one was passed
            Item clientItem;

            if (req.Content.Headers.ContentLength > 0)
            {
                clientItem = null;
                code       = ProcessRequestBody(req, out clientItem, out operation);
                if (code != HttpStatusCode.OK)  // error encountered processing body
                {
                    return(ReturnResult <Item>(req, operation, code));
                }

                if (clientItem.ID != id)
                {   // IDs must match
                    TraceLog.TraceError("ItemResource.Delete: Bad Request (ID in URL does not match entity body)");
                    return(ReturnResult <Item>(req, operation, HttpStatusCode.BadRequest));
                }
            }
            else
            {
                // otherwise get the client item from the database
                try
                {
                    clientItem = this.StorageContext.Items.Single <Item>(i => i.ID == id);
                    var session = GetSessionFromMessageHeaders(req);
                    operation = this.StorageContext.CreateOperation(CurrentUser, req.Method.Method, null, clientItem, null, session);
                }
                catch (Exception)
                {   // item not found - it may have been deleted by someone else.  Return 200 OK along with a dummy item.
                    TraceLog.TraceInfo("ItemResource.Delete: entity not found; returned OK anyway");
                    return(ReturnResult <Item>(req, operation, new Item()
                    {
                        Name = "Item Not Found"
                    }, HttpStatusCode.OK));
                }
            }

            try
            {
                Folder folder = this.StorageContext.Folders.Single <Folder>(tl => tl.ID == clientItem.FolderID);
                if (folder.UserID != CurrentUser.ID)
                {   // requested item does not belong to the authenticated user, return 403 Forbidden
                    TraceLog.TraceError("ItemResource.Delete: Forbidden (entity's folder does not belong to current user)");
                    return(ReturnResult <Item>(req, operation, HttpStatusCode.Forbidden));
                }

                try
                {
                    Item requestedItem = this.StorageContext.Items.Include("ItemTags").Include("FieldValues").Single <Item>(t => t.ID == id);

                    // process the delete BEFORE deleting item, fields, references, etc.
                    ItemProcessor ip = ItemProcessor.Create(CurrentUser, StorageContext, requestedItem.ItemTypeID);
                    if (ip != null)
                    {   // do itemtype-specific processing
                        ip.ProcessDelete(requestedItem);
                    }

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

                    // delete all the fieldvalues associated with this item
                    if (requestedItem.FieldValues != null && requestedItem.FieldValues.Count > 0)
                    {
                        foreach (var fv in requestedItem.FieldValues.ToList())
                        {
                            this.StorageContext.FieldValues.Remove(fv);
                        }
                    }

                    bool multipleItemsDeleted = false;
                    // delete all the items with ParentID of this item.ID (recursively, from the bottom up)
                    multipleItemsDeleted = DeleteItemChildrenRecursively(StorageContext, requestedItem);
                    // delete all ItemRef FieldValues with Value of this item.ID
                    multipleItemsDeleted |= DeleteItemReferences(CurrentUser, StorageContext, requestedItem);

                    // TODO: indicate using TimeStamp that multiple items were deleted

                    this.StorageContext.Items.Remove(requestedItem);
                    if (this.StorageContext.SaveChanges() < 1)
                    {
                        TraceLog.TraceError("Internal Server Error (database operation did not succeed)");
                        return(ReturnResult <Item>(req, operation, HttpStatusCode.InternalServerError));
                    }
                    else
                    {
                        if (folder.Name.StartsWith("$") == false)
                        {
                            WorkflowHost.WorkflowHost.InvokeWorkflowForOperation(this.StorageContext, null, operation);
                        }
                        TraceLog.TraceInfo("Accepted");
                        return(ReturnResult <Item>(req, operation, requestedItem, HttpStatusCode.Accepted));
                    }
                }
                catch (Exception ex)
                {   // item not found - it may have been deleted by someone else.  Return 200 OK along with a dummy item.
                    TraceLog.TraceInfo(String.Format("Exception in database operation, return OK : Exception[{0}]", ex.Message));
                    return(ReturnResult <Item>(req, operation, new Item()
                    {
                        Name = "Item Not Found"
                    }, HttpStatusCode.OK));
                }
            }
            catch (Exception ex)
            {   // folder not found - return 404 Not Found
                TraceLog.TraceException(String.Format("Resource not found (Folder)"), ex);
                return(ReturnResult <Item>(req, operation, HttpStatusCode.NotFound));
            }
        }
Ejemplo n.º 2
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));
            }
        }
Ejemplo n.º 3
0
        public HttpResponseMessageWrapper <Item> InsertItem(HttpRequestMessage req)
        {
            Operation      operation = null;
            HttpStatusCode code      = AuthenticateUser(req);

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

            // get the new item from the message body
            Item clientItem = null;

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

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

            try
            {
                Folder folder = this.StorageContext.Folders.Single <Folder>(tl => tl.ID == clientItem.FolderID);
                if (folder.UserID != CurrentUser.ID)
                {   // requested folder 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));
                }

                // fill out the ID's for any FieldValues that travelled with the item
                if (clientItem.FieldValues != null)
                {
                    foreach (var fv in clientItem.FieldValues)
                    {
                        if (fv.ItemID == null || fv.ItemID == Guid.Empty)
                        {
                            fv.ItemID = clientItem.ID;
                        }
                    }
                }

                // fill out the timestamps if they aren't set (null, or MinValue.Date, allowing for DST and timezone issues)
                DateTime now = DateTime.UtcNow;
                if (clientItem.Created == null || clientItem.Created.Date == DateTime.MinValue.Date)
                {
                    clientItem.Created = now;
                }
                if (clientItem.LastModified == null || clientItem.LastModified.Date == DateTime.MinValue.Date)
                {
                    clientItem.LastModified = now;
                }

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

                try
                {   // add the new item to the database
                    var item = this.StorageContext.Items.Add(clientItem);
                    int rows = this.StorageContext.SaveChanges();
                    if (rows < 1 || item == null)
                    {
                        TraceLog.TraceError("Internal Server Error (database operation did not succeed)");
                        return(ReturnResult <Item>(req, operation, HttpStatusCode.InternalServerError));  // return 500 Internal Server Error
                    }
                    else
                    {
                        // invoke any workflows associated with this item
                        if (folder.Name.StartsWith("$") == false)
                        {
                            WorkflowHost.WorkflowHost.InvokeWorkflowForOperation(this.StorageContext, null, operation);
                        }
                        TraceLog.TraceInfo("Created");
                        return(ReturnResult <Item>(req, operation, item, HttpStatusCode.Created));     // return 201 Created
                    }
                }
                catch (Exception ex)
                {   // check for the condition where the item is already in the database
                    // in that case, return 202 Accepted; otherwise, return 500 Internal Server Error
                    try
                    {
                        var dbItem = this.StorageContext.Items.Single(t => t.ID == clientItem.ID);
                        if (dbItem.Name == clientItem.Name)
                        {
                            TraceLog.TraceInfo("Accepted (entity already in database) : Exception[" + ex.Message + "]");
                            return(ReturnResult <Item>(req, operation, dbItem, HttpStatusCode.Accepted));
                        }
                        else
                        {
                            TraceLog.TraceException("Error inserting entity", ex);
                            return(ReturnResult <Item>(req, operation, HttpStatusCode.InternalServerError));
                        }
                    }
                    catch (Exception)
                    {   // item not inserted - return 500 Internal Server Error
                        TraceLog.TraceException("Error inserting entity", ex);
                        return(ReturnResult <Item>(req, operation, HttpStatusCode.InternalServerError));
                    }
                }
            }
            catch (Exception ex)
            {   // folder not found - return 404 Not Found
                TraceLog.TraceException("Resource not found (Folder)", ex);
                return(ReturnResult <Item>(req, operation, HttpStatusCode.NotFound));
            }
        }