Ejemplo n.º 1
0
        public async Task <bool> DeleteCalendarCollection(Dictionary <string, string> propertiesAndHeaders,
                                                          HttpResponse response)
        {
            #region Extracting Properties

            string url;
            propertiesAndHeaders.TryGetValue("url", out url);

            #endregion

            //The delete method default status code
            response.StatusCode = (int)HttpStatusCode.NoContent;
            //If the collection already is gone it is treated as a successful operation.
            if (!StorageManagement.ExistCalendarCollection(url))
            {
                return(true);
            }

            //The collection is retrieve and if something unexpected happened an internal error is reflected.
            var collection = _collectionRespository.Get(url);
            if (collection == null)
            {
                StorageManagement.DeleteCalendarCollection(url);
                response.StatusCode = (int)HttpStatusCode.InternalServerError;
                return(false);
            }


            await _collectionRespository.Remove(collection);

            return(StorageManagement.DeleteCalendarCollection(url));
        }
Ejemplo n.º 2
0
        public async Task AllPropMethod(string url, string calendarResourceId, int?depth,
                                        List <KeyValuePair <string, string> > aditionalProperties, XmlTreeStructure multistatusTree)
        {
            //error flag

            //Here it is created the response body for the collection or resource
            //It depends if calendarResourceId == null.
            var primaryResponse = await AllPropFillTree(url, calendarResourceId, aditionalProperties);

            //The response body is added to the result xml tree.
            multistatusTree.AddChild(primaryResponse);

            //check if there was any error
            IXMLTreeStructure errorNode;
            var errorOcurred = primaryResponse.GetChildAtAnyLevel("responsedescription", out errorNode);

            //Now I start putting all objectResource responses if the primary target was a collection
            //and if depth is greater than depth 0.

            #region Adding the responses for resources.

            if (calendarResourceId == null && depth == 1 || depth == -1)
            {
                var collection = _collectionRepository.Get(url);

                foreach (var calendarResource in collection.CalendarResources)
                {
                    //For every resource in the collection it is added a new xml "response"
                    var resourceResponse = await AllPropFillTree(url + calendarResource.Name, calendarResource.Name,
                                                                 aditionalProperties);

                    multistatusTree.AddChild(resourceResponse);

                    //error check
                    if (!errorOcurred)
                    {
                        errorOcurred = resourceResponse.GetChildAtAnyLevel("responsedescription", out errorNode);
                    }
                }
            }
            if (errorOcurred)
            {
                //if an error occured it is added a new "responsedescription" with a message of the error
                //to the root of the tree. That is the "multistatus" xml.
                errorNode = new XmlTreeStructure("responsedescription", "DAV:");
                errorNode.AddValue("There has been an error");
                multistatusTree.AddChild(errorNode);
            }

            #endregion
        }
        public void User_Can_Add_Collection()
        {
            // Get a userId
            int userId = 1;

            // Create a new collection
            Collection collection = new Collection()
            {
                UserId           = 1,
                CategorizationId = 1,
                Name             = "New stuff",
                Description      = "New lame description.",
                Pinned           = false,
                CreationDate     = DateTime.Now - TimeSpan.FromDays(10)
            };

            // Instantiate CollectionRepo
            var repo = new CollectionRepository(_context);

            // Add collection
            repo.Add(collection);

            // Get new count of all collections
            var count = repo.Get(userId).Count;

            // User with Id 1 should have 3
            Assert.True(count == 3);
        }
        public void User_Can_Delete_Collection()
        {
            // Get an object that's in the database
            var collectionToAdd = new Collection()
            {
                UserId           = 1,
                CategorizationId = 1,
                Name             = "New Collection to Axe",
                Description      = "Blah",
                Pinned           = false,
                CreationDate     = DateTime.Now - TimeSpan.FromDays(15)
            };

            // Add collectionToAdd to collectionDetailsVm
            var collectionDetails = new CollectionDetailsViewModel
            {
                Collection         = collectionToAdd,
                ProjectCollections = new List <ProjectCollection>(),
                Words = new List <Word>()
            };

            // Instantiate CollectionRepo
            var repo = new CollectionRepository(_context);

            // Get a count of Collections for UserId 1
            var count = repo.Get(1).Count;

            // Add new collection
            repo.Add(collectionToAdd);

            // Get a new count
            var countAfterAdd = repo.Get(1).Count;

            // Attempt to delete the collection
            repo.Delete(collectionDetails);

            // New count after deleting
            var countAfterDeletion = repo.Get(1).Count;

            // We successfully added one collection
            Assert.True(count < countAfterAdd);
            // We successfully deleted one collection
            Assert.True(count == countAfterDeletion);
        }
        public void User_Can_Get_Their_Collections()
        {
            // Get a userId
            int userId = 1;

            // Instantiate CollectionRepo
            var repo = new CollectionRepository(_context);

            // Get count of all collections
            var count = repo.Get(userId).Count;

            // User with Id 1 should have 2
            Assert.True(count == 2);
        }
Ejemplo n.º 6
0
        /// <summary>
        ///     The DAV:principal-match REPORT is used to identify all members (at
        ///     any depth) of the collection identified by the Request-URI that are
        ///     principals and that match the current user.
        ///     So it takes the resources of the collection and see wich ones match
        ///     the given principal. This is done comparing the principal's email
        ///     of the resource with the email of the given principal.
        /// </summary>
        /// <returns></returns>
        public async Task PrincipalMatch(IXMLTreeStructure body, string principalEmail, string href,
                                         HttpResponse response)
        {
            //take the collection with the given href
            var col = _collectionRepository.Get(href);

            //if the collection doesnt exit then return an error
            if (col == null)
            {
                await ReturnError(response, "Not Found", 404, href);
            }

            //take all the resources from the collection.
            //var colResources = col.CalendarResources.Where(x=>x.)
        }
Ejemplo n.º 7
0
        public async Task <bool> PreconditionsOK(Dictionary <string, string> propertiesAndHeaders, HttpResponse response)
        {
            #region Extracting Properties

            var url = propertiesAndHeaders["url"];

            var       contentSize = propertiesAndHeaders["content-length"];
            var       body        = propertiesAndHeaders["body"];
            VCalendar iCalendar;
            try
            {
                iCalendar = new VCalendar(body); //lo que no estoy seguro que en el body solo haya el iCal string
            }
            catch (Exception)
            {
                response.StatusCode = (int)HttpStatusCode.BadRequest;
                return(false);
            }

            #endregion

            //check that resourceId don't exist but the collection does.
            if (
                !StorageManagement.ExistCalendarCollection(url.Remove(url.LastIndexOf("/", StringComparison.Ordinal) + 1)))
            {
                response.StatusCode = (int)HttpStatusCode.NotFound;
                return(false);
            }


            //check that if the resource exist then all its components different of VTIMEZONE has to have the same UID
            //if the resource not exist can not be another resource with the same uid.
            if (!StorageManagement.ExistCalendarObjectResource(url))
            {
                var component = iCalendar.CalendarComponents.FirstOrDefault(comp => comp.Key != "VTIMEZONE").Value;
                var uid       = component.FirstOrDefault()?.Properties["UID"].StringValue;
                // var resource = db.GetCalendarResource(userEmail, collectionName, calendarResourceId);
                var collection =
                    _collectionRepository.Get(url.Remove(url.LastIndexOf("/", StringComparison.Ordinal) + 1));
                foreach (var calendarresource in collection.CalendarResources)
                {
                    if (uid == calendarresource.Uid)
                    {
                        response.StatusCode = (int)HttpStatusCode.Conflict;
                        response.Body.Write(
                            $@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<no-uid-conflict xmlns='urn:ietf:params:xml:ns:caldav'>
<href xmlns='DAV:'>{
                                SystemProperties._baseUrl + calendarresource
                                    .Href}</href>
</no-uid-conflict>
</error>");
                        return(false);
                    }
                }
            }
            else
            {
                //If the resource exist the procedure is update and for that the uid has to be the same.
                var components        = iCalendar.CalendarComponents.FirstOrDefault(comp => comp.Key != "VTIMEZONE").Value;
                var calendarComponent = components.FirstOrDefault();
                if (calendarComponent != null)
                {
                    var uid = calendarComponent.Properties["UID"].StringValue;

                    var resource = _resourceRespository.Get(url);

                    if (resource.Uid != null && resource.Uid != uid)
                    {
                        response.StatusCode = (int)HttpStatusCode.Conflict;
                        response.Body.Write(
                            $@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<no-uid-conflict xmlns='urn:ietf:params:xml:ns:caldav'>
<href xmlns='DAV:'>{
                                SystemProperties._baseUrl + resource
                                    .Href}</href>
</no-uid-conflict>
</error>");
                        return(false);
                    }
                }
            }


            if (propertiesAndHeaders.ContainsKey("If-Match"))
            {
                //check that the value do exist
                if (!StorageManagement.ExistCalendarObjectResource(url))
                {
                    response.StatusCode = (int)HttpStatusCode.PreconditionFailed;
                    return(false);
                }
            }

            if (propertiesAndHeaders.ContainsKey("If-None-Match"))
            {
                //check that the value do not exist
                if (StorageManagement.ExistCalendarObjectResource(url))
                {
                    response.StatusCode = (int)HttpStatusCode.PreconditionFailed;
                    return(false);
                }
            }


            //it does not contain more than two calendar components
            //and if it has 2, one must be VTIMEZONE
            if (iCalendar.CalendarComponents.Count > 2)
            {
                if (!iCalendar.CalendarComponents.ContainsKey("VTIMEZONE"))
                {
                    response.StatusCode = (int)HttpStatusCode.Conflict;
                    response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource>
<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'>
VTimezone Calendar Component Must be present.
</error-description>
</error>");
                    return(false);
                }

                var calendarComponents =
                    iCalendar.CalendarComponents.FirstOrDefault(comp => comp.Key != "VTIMEZONE").Value;

                //A Calendar Component can be separated in multiples calendar components but all MUST
                //have the same UID.
                var calendarComponent = calendarComponents.FirstOrDefault();
                if (calendarComponent != null)
                {
                    var uid = calendarComponent.Properties["UID"].StringValue;
                    foreach (var component in calendarComponents)
                    {
                        var uidComp = component.Properties["UID"].StringValue;
                        if (uid != uidComp)
                        {
                            response.StatusCode = (int)HttpStatusCode.Conflict;
                            response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource>
<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'>
If the count of calendar components execeds 2 including VTimezone the rest must have the same Uid and the same type.
</error-description>
</error>");
                            return(false);
                        }
                    }
                }

                //                response.StatusCode = (int)HttpStatusCode.Conflict;
                //                response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?>
                //<error xmlns='DAV:'>
                //<valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource>
                //<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'>
                //Wrong amount of calendar components
                //</error-description>
                //</error>");
                //                return false;
            }

            //precondition responsible of check that an VTIMEZONE is obligatory
            if (iCalendar.CalendarComponents.Count == 2)
            {
                if (!iCalendar.CalendarComponents.ContainsKey("VTIMEZONE"))
                {
                    response.StatusCode = (int)HttpStatusCode.Conflict;
                    response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource>
<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'>
VTimezone Calendar Component Must be present.
</error-description>
</error>");
                    return(false);
                }
            }


            //var uidCalendar = ((ComponentProperty<string>)iCalendar.Properties["UID"]).Value;
            ////Check that if the operation is create there is not another element in the collection with the same UID
            //if (!StorageManagement.ExistCalendarObjectResource(calendarResourceId))
            //{
            //    using (db)
            //    {
            //        if ((from calendarResource in db.CalendarResources
            //             where calendarResource.Uid == uidCalendar
            //             select calendarResource).Count() > 0)
            //            return false;

            //    }
            //}
            ////Check if the operation is update the element to be updated must have the same UID.
            //else
            //{
            //    using (db)
            //    {
            //        if ((from calendarResource in db.CalendarResources
            //             where calendarResource.Uid == uidCalendar
            //             select calendarResource).Count() == 0)
            //            return false;

            //    }
            //}

            var methodProp = iCalendar.GetComponentProperties("METHOD");
            //iCalendar object MUST NOT implement METHOD property
            if (!string.IsNullOrEmpty(methodProp?.StringValue))
            {
                response.StatusCode = (int)HttpStatusCode.Conflict;
                response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<valid-calendar-object-resource xmlns='urn:ietf:params:xml:ns:caldav'></valid-calendar-object-resource>
<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'>
Method prop must not be present
</error-description>
</error>");
                return(false);
            }

            //This precondition is the one in charge of check that the size of the body of the resource
            //included in the request dont exceeds the max-resource-size property of the colletion.
            int contentSizeInt;
            //for that i need that the controller has as request header content-size available
            if (!string.IsNullOrEmpty(contentSize) && int.TryParse(contentSize, out contentSizeInt))
            {
                var collection =
                    _collectionRepository.Get(url.Remove(url.LastIndexOf("/", StringComparison.Ordinal) + 1));
                //here the max-resource-property of the collection is called.
                var maxSize =
                    collection.Properties.FirstOrDefault(
                        p => p.Name == "max-resource-size" && p.Namespace == "urn:ietf:params:xml:ns:caldav");
                int maxSizeInt;
                if (int.TryParse(XmlTreeStructure.Parse(maxSize?.Value).Value, out maxSizeInt) &&
                    contentSizeInt > maxSizeInt)
                {
                    response.StatusCode = (int)HttpStatusCode.Conflict;
                    response.Body.Write(@"<?xml version='1.0' encoding='UTF-8'?>
<error xmlns='DAV:'>
<max-resource-size xmlns='urn:ietf:params:xml:ns:caldav'></max-resource-size>
<error-description xmlns='http://twistedmatrix.com/xml_namespace/dav/'>
Content size exceeds max size allowed.
</error-description>
</error>");
                    return(false);
                }
            }


            //TODO: Checking that all DateTime values are less-equal than
            //the max-date-time

            //TODO: Checking that all DateTime values are grater-equal than
            //the min-date-time

            //TODO: Checking that the number of recurring instances is less-equal
            //than the max-instances property value.

            return(await Task.FromResult(true));
        }