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)); }
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); }
/// <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.) }
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)); }