public RaterModel Rate(Id entryId, float rating, User user, string ip) { LogService.Info("Rater.Rate entryId={0} rating={1} ip={2}", entryId, rating, ip); if (!AuthorizeService.IsAuthorized(user, entryId.ToScope(), AuthAction.RateEntryOrMedia)) throw new UserNotAuthorizedException(user.Name, AuthAction.RateEntryOrMedia.ToString()); if (rating < 1 || rating > 5) throw new ArgumentOutOfRangeException("Rating value must be 1 thru 5."); AtomEntry entry = AtomEntryRepository.GetEntry(entryId); if (entry.Raters.Contains(ip)) throw new UserAlreadyRatedEntryException(ip, entry.Id.ToString()); entry.RatingCount++; entry.RatingSum += (int)Math.Round(rating); entry.Edited = DateTimeOffset.UtcNow; List<string> raters = entry.Raters.ToList(); raters.Add(ip); entry.Raters = raters; entry = AtomEntryRepository.UpdateEntry(entry); return new RaterModel() { PostHref = RouteService.RouteUrl("RaterRateEntry", entryId), Rating = entry.Rating, CanRate = false, RatingCount = entry.RatingCount }; }
public RaterModel GetRaterModel(Id entryId, User user, string ip) { bool auth = AuthorizeService.IsAuthorized(user, entryId.ToScope(), AuthAction.RateEntryOrMedia); AtomEntry entry = AtomEntryRepository.GetEntry(entryId); return new RaterModel() { PostHref = RouteService.RouteUrl("RaterRateEntry", entryId), Rating = entry.Rating, CanRate = auth && !entry.Raters.Contains(ip), RatingCount = entry.RatingCount }; }
public virtual AtomEntry Annotate(Id entryId, AtomEntry entry, string slug) { LogService.Info("AnnotateService.Annotate entryId={0} slug={1}", entryId, slug); //authorization if (!AuthorizeService.IsAuthorized(GetUser(), entryId.ToScope(), AuthAction.Annotate)) throw new UserNotAuthorizedException(GetUser().Name, AuthAction.Annotate.ToString()); AppCollection coll = AppService.GetCollection(entryId); //make sure type is accepted if (!coll.CanAccept(Atom.ContentTypeEntry)) throw new InvalidContentTypeException(Atom.ContentTypeEntry); entry.SetNamespaces(); //TODO: is there a better place for this? //build id onto parent's id AtomEntry parent = AtomPubService.GetEntry(entryId); entry.Id = new Id(parent.Id.Owner, parent.Id.Date, parent.Id.Collection, entry.BuildPath(parent.Id.EntryPath, slug)); var url = new UrlHelper(Container.GetInstance<RequestContext>()); //this annotation is a reply to the parent entry, TODO: leave off href for later calc based on id? entry.InReplyTo = new ThreadInReplyTo() { Ref = parent.Id, Href = parent.IsExternal ? parent.Content.Src : url.RouteIdUri("AtomPubEntry", entry.Id, AbsoluteMode.Force), Type = parent.IsExternal ? parent.Content.Type : Atom.ContentTypeEntry }; if (!entry.Published.HasValue) entry.Published = DateTimeOffset.UtcNow; entry.Updated = DateTimeOffset.UtcNow; entry.Edited = DateTimeOffset.UtcNow; if (entry.Authors.Count() == 0) entry.SetPerson(AuthorizeService, true); //entry.IdChanged += (e) => e.UpdateLinks(UrlHelper.RouteIdUri); //OnAnnotate(parent, entryId, entry, slug); if (AnnotatingEntry != null) AnnotatingEntry(entryId, entry, slug); if (entry.Authors.Count() == 0 || entry.Authors.First().Name == null) throw new AnnotationNotAllowedException(entry.Id, entry.AnnotationType, "the author cannot be determined"); entry = AtomEntryRepository.CreateEntry(entry); if (EntryAnnotated != null) EntryAnnotated(entry); return entry; }
protected void Auth(Id id, AuthAction action) { User user = GetUser(); if (!AuthorizeService.IsAuthorized(user, id.ToScope(), action)) throw new UserNotAuthorizedException(user.Name, action.ToString()); }
public int ApproveAll(Id id) { LogService.Info("AtomPubService.ApproveAll id={0}", id); AuthorizeService.Auth(id.ToScope(), AuthAction.ApproveEntryOrMedia); return AtomEntryRepository.ApproveAll(id); }
public void ApproveEntry(Id entryId, bool approved) { LogService.Info("AtomPubService.ApproveEntry entryId={0}", entryId); AuthorizeService.Auth(entryId.ToScope(), AuthAction.ApproveEntryOrMedia); AtomEntry e = AtomEntryRepository.GetEntry(entryId); if (e.Control == null) e.Control = new AppControl(); e.Control.Approved = approved; AtomEntryRepository.UpdateEntry(e); }
public virtual Stream GetMedia(Id entryId, out string contentType) { LogService.Info("AtomPubService.GetMedia entryId={0}", entryId); AtomEntry mediaLinkEntry = AtomEntryRepository.GetEntry(entryId); contentType = mediaLinkEntry.Content.Type; //TODO: remove this hack SetLinks(mediaLinkEntry); //mediaLinkEntry.Content.Src = UrlHelper.RouteIdUri("AtomPubMedia", mediaLinkEntry.Id, AbsoluteMode.Force); //Allow authorized users to get media otherwise only get if visible if (AuthorizeService.IsAuthorized(GetUser(), entryId.ToScope(), AuthAction.GetEntryOrMedia)) return MediaRepository.GetMedia(mediaLinkEntry); else if (mediaLinkEntry.Visible) { //TODO: clean private data return MediaRepository.GetMedia(mediaLinkEntry); } throw new UserNotAuthorizedException(GetUser().Name, AuthAction.GetEntryOrMedia.ToString()); }
public virtual AtomEntry UpdateEntry(Id entryId, AtomEntry entry, string slug) { LogService.Info("AtomPubService.UpdateEntry entryId={0}", entryId); Auth(entryId, AuthAction.UpdateEntryOrMedia); //ensure existing entry exists AtomEntry old = AtomEntryRepository.GetEntry(entryId); //copy old approval setting when not authorized to approve if (!AuthorizeService.IsAuthorized(GetUser(), entryId.ToScope(), AuthAction.ApproveEntryOrMedia)) { if (entry.Control != null && entry.Control.Approved.HasValue) entry.Control.Approved = old.Control.Approved; else entry.Control.Approved = false; } if (!entry.Draft && !entry.Published.HasValue) entry.Published = DateTimeOffset.UtcNow; entry.Updated = DateTimeOffset.UtcNow; entry.Edited = DateTimeOffset.UtcNow; //if (old.Draft) //allow Id to change when old was draft mode, is this safe? //{ // AppCollection coll = AppServiceRepository.GetService().GetCollection(entryId); // if (coll.Dated) // entry.Id = new Id(coll.Id.Owner, entry.Date.UtcDateTime, coll.Id.Collection, entry.BuildPath(null, slug)); // else // entry.Id = new Id(coll.Id.Owner, coll.Id.Date, coll.Id.Collection, entry.BuildPath(null, slug)); //} //else entry.Id = entryId; //reset Id (it shouldn't change) if (old.Media) entry.Content = old.Content; //reset Content (it shouldn't change for media link entries) //entry.UpdateLinks(RouteFunc); SetPerson(entry); SetCategories(entry); SetLinks(entry); entry.IdChanged += (e) => SetLinks(e);// e.UpdateLinks(RouteFunc); //in case of changes during draft if (UpdatingEntry != null) UpdatingEntry(entryId, entry, slug); entry = AtomEntryRepository.UpdateEntry(entry); if (EntryUpdated != null) EntryUpdated(entry); return entry; }
public virtual AtomEntry CreateEntry(Id collectionId, AtomEntry entry, string slug) { LogService.Info("AtomPubService.CreateEntry collectionId={0} slug={1}", collectionId, slug); Auth(collectionId, AuthAction.CreateEntryOrMedia); AppCollection coll = AppServiceRepository.GetService().GetCollection(collectionId); if (entry.Control == null) entry.Control = new AppControl(); //is acceptable type? if (!coll.CanAccept(Atom.ContentTypeEntry)) throw new InvalidContentTypeException(Atom.ContentTypeEntry); //approval based on role action matrix if (!AuthorizeService.IsAuthorized(GetUser(), collectionId.ToScope(), AuthAction.ApproveEntryOrMedia)) entry.Control.Approved = false; if (!entry.Draft && !entry.Published.HasValue) entry.Published = DateTimeOffset.UtcNow; if (entry.Updated == default(DateTimeOffset)) entry.Updated = DateTimeOffset.UtcNow; entry.Edited = DateTimeOffset.UtcNow; if (coll.Dated) entry.Id = new Id(collectionId.Owner, entry.Date.UtcDateTime, collectionId.Collection, entry.BuildPath(null, slug)); else entry.Id = new Id(collectionId.Owner, collectionId.Date, collectionId.Collection, entry.BuildPath(null, slug)); SetPerson(entry); SetCategories(entry); SetLinks(entry); entry.IdChanged += (e) => SetLinks(e); if (CreatingEntry != null) CreatingEntry(collectionId, entry, slug); entry = AtomEntryRepository.CreateEntry(entry); if (EntryCreated != null) EntryCreated(entry); return entry; }
public virtual AtomFeed GetFeedBySearch(Id collectionId, string term, int pageIndex, int pageSize) { LogService.Info("AtomPubService.GetFeedBySearch collectionId={0} term={1} pageIndex={2}", collectionId, term, pageIndex); Auth(collectionId, AuthAction.GetFeed); AppCollection c = AppServiceRepository.GetService().GetCollection(collectionId); EntryCriteria criteria = new EntryCriteria() { WorkspaceName = collectionId.Workspace, CollectionName = collectionId.Collection, SearchTerm = term, Authorized = AuthorizeService.IsAuthorized(GetUser(), collectionId.ToScope(), AuthAction.GetEntryOrMedia) }; int total; //search annotations? AtomFeed feed = AtomFeed.BuildFeed(c, AtomEntryRepository.GetEntries(criteria, pageIndex, pageSize, out total), total);//, pageIndex, pageSize, RouteFunc, "AtomPubFeed", "AtomPubCollectionIndex", false); feed.Subtitle = new AtomSubtitle { Text = "Search for '" + term + "'" }; SetLinks(feed); return feed; }
public virtual AtomFeed GetFeedByCategory(Id collectionId, string term, Uri scheme, int pageIndex, int pageSize) { LogService.Info("AtomPubService.GetFeedByCategory collectionId={0}, term={1}", collectionId, term); Auth(collectionId, AuthAction.GetFeed); AppCollection c = AppServiceRepository.GetService().GetCollection(collectionId); //TODO: support external categories AtomCategory category = c.Categories.SelectMany(cats => cats.Categories).Where(cat => cat.Term == term && cat.Scheme == scheme).SingleOrDefault(); if (category == null) throw new ResourceNotFoundException("category", term); EntryCriteria criteria = new EntryCriteria() { WorkspaceName = collectionId.Workspace, CollectionName = collectionId.Collection, CategoryTerm = term, CategoryScheme = scheme, Authorized = AuthorizeService.IsAuthorized(GetUser(), collectionId.ToScope(), AuthAction.GetEntryOrMedia) }; int total; AtomFeed feed = AtomFeed.BuildFeed(c, AtomEntryRepository.GetEntries(criteria, pageIndex, pageSize, out total), total);//, pageIndex, pageSize, RouteFunc, "AtomPubFeed", "AtomPubCollectionIndex", false); feed.Subtitle = new AtomSubtitle { Text = "Browsing " + category.ToString() }; SetLinks(feed); return feed; }
public virtual AtomFeed GetFeedByPerson(Id collectionId, string personName, int pageIndex, int pageSize) { LogService.Info("AtomPubService.GetFeedByPerson collectionId={0}, personName={1}", collectionId, personName); Auth(collectionId, AuthAction.GetFeed); AppCollection c = AppServiceRepository.GetService().GetCollection(collectionId); EntryCriteria criteria = new EntryCriteria() { WorkspaceName = collectionId.Workspace, CollectionName = collectionId.Collection, PersonName = personName, PersonType = "person", Authorized = AuthorizeService.IsAuthorized(GetUser(), collectionId.ToScope(), AuthAction.GetEntryOrMedia) }; int total; AtomFeed feed = AtomFeed.BuildFeed(c, AtomEntryRepository.GetEntries(criteria, pageIndex, pageSize, out total), total);//, pageIndex, pageSize, RouteFunc, "AtomPubFeed", "AtomPubCollectionIndex", false); feed.Subtitle = new AtomSubtitle() { Text = personName }; SetLinks(feed); return feed; }
public virtual AtomFeed GetFeedByDate(Id collectionId, DateTime startDate, DateTime endDate, int pageIndex, int pageSize) { LogService.Info("AtomPubService.GetFeedByDate collectionId={0}, startDate={1}, endDate={2}", collectionId, startDate, endDate); Auth(collectionId, AuthAction.GetFeed); AppCollection c = AppServiceRepository.GetService().GetCollection(collectionId); EntryCriteria criteria = new EntryCriteria() { WorkspaceName = collectionId.Workspace, CollectionName = collectionId.Collection, StartDate = startDate, EndDate = endDate, Authorized = AuthorizeService.IsAuthorized(GetUser(), collectionId.ToScope(), AuthAction.GetEntryOrMedia) }; int total; AtomFeed feed = AtomFeed.BuildFeed(c, AtomEntryRepository.GetEntries(criteria, pageIndex, pageSize, out total), total);//, pageIndex, pageSize, RouteFunc, "AtomPubFeed", "AtomPubCollectionIndex", false); if (startDate.DayOfYear == 1 && endDate.DayOfYear > 354) { feed.Subtitle = new AtomSubtitle() { Text = "For the year " + startDate.Year.ToString("0000") }; } else if (startDate.Day == 1 && endDate.Day == DateTime.DaysInMonth(endDate.Year, endDate.Month)) { feed.Subtitle = new AtomSubtitle() { Text = "For " + startDate.ToString("MMMM yyyy") }; } else if (startDate.Day == endDate.Day) { feed.Subtitle = new AtomSubtitle() { Text = "For " + startDate.ToString("D") }; } else { feed.Subtitle = new AtomSubtitle() { Text = "From " + startDate.ToShortDateString() + " to " + endDate.ToShortDateString() }; } SetLinks(feed); return feed; }
public virtual AtomFeed GetFeed(Id collectionId, int pageIndex, int pageSize) { //<atom:link rel="alternate" type="text/html" href="https://atomsite.net/blog.xhtml" /> LogService.Info("AtomPubService.GetFeed collectionId={0}", collectionId); Auth(collectionId, AuthAction.GetFeed); AppCollection c = AppServiceRepository.GetService().GetCollection(collectionId); EntryCriteria criteria = new EntryCriteria() { WorkspaceName = collectionId.Workspace, CollectionName = collectionId.Collection, Authorized = AuthorizeService.IsAuthorized(GetUser(), collectionId.ToScope(), AuthAction.GetEntryOrMedia), }; int total; AtomFeed feed = AtomFeed.BuildFeed(c, AtomEntryRepository.GetEntries(criteria, pageIndex, pageSize, out total), total);//, pageIndex, pageSize, RouteFunc, "AtomPubFeed", "AtomPubCollectionIndex", true); var url = new UrlHelper(Container.GetInstance<RequestContext>()); feed.Links = feed.Links.Concat(url.GetPagingLinks("AtomPubFeed", feed.Id, null, feed.TotalResults ?? 0, pageIndex, pageSize,Atom.ContentTypeFeed, AbsoluteMode.Force)); SetLinks(feed); return feed; }
public virtual AtomFeed GetAnnotations(Id id, bool deep, int pageIndex, int pageSize) { LogService.Info("AnnotateService.GetAnnotations: {0} deep={1}", id, deep); //authorization if (!AuthorizeService.IsAuthorized(GetUser(), id.ToScope(), AuthAction.GetAnnotations)) throw new UserNotAuthorizedException(GetUser().Name, AuthAction.GetAnnotations.ToString()); return GetAnnotations(new EntryCriteria() { EntryId = id.EntryPath != null ? id : null, WorkspaceName = id.EntryPath == null ? id.Workspace : null, CollectionName = id.EntryPath == null ? id.Collection : null, SortMethod = id.EntryPath == null ? SortMethod.DateDesc : SortMethod.Default, Authorized = AuthorizeService.IsAuthorized(GetUser(), id.ToScope(), AuthAction.GetEntryOrMedia), Annotations = true, Deep = deep }, pageIndex, pageSize); }
/// <summary> /// Get an entry from the collection. This method supports Anonymous /// retrieval. /// </summary> /// <param name="entryId"></param> /// <returns></returns> public virtual AtomEntry GetEntry(Id entryId) { LogService.Info("AtomPubService.GetEntry entryId={0}", entryId); AtomEntry entry = AtomEntryRepository.GetEntry(entryId); SetLinks(entry); //entry.UpdateLinks(RouteFunc); //OnGetEntry(entry); //Allow authorized users to get entry otherwise only get if visible if (AuthorizeService.IsAuthorized(GetUser(), entryId.ToScope(), AuthAction.GetEntryOrMedia)) return entry; else if (entry.Visible) { //TODO: clean private data return entry; } throw new UserNotAuthorizedException(GetUser().Name, AuthAction.GetEntryOrMedia.ToString()); }
public virtual AnnotationState GetAnnotationState(AppCollection coll, Id entryId) { LogService.Info("AnnotateService.GetAnnotationState entryId={0}", entryId); if (!coll.AnnotationsOn) { return AnnotationState.Off; } else if (!AuthorizeService.IsAuthorized(GetUser(), entryId.ToScope(), AuthAction.Annotate)) { return AnnotationState.Unauthorized; } else if (!AtomEntryRepository.GetEntry(entryId).AllowAnnotate) { return AnnotationState.Closed; } //TODO: handle expired return AnnotationState.On; }
protected void OnAnnotateEntry(Id entryId, AtomEntry entry, string slug) { LogService.Info("BlogService.OnAnnotateEntry"); if (!new BlogAppCollection(AppService.GetCollection(entryId)).BloggingOn) return; //TODO: check if author url (referrer) is blocked //TODO: check if content src is blocked //TODO: check if spam if (entry.AnnotationType == null) entry.AnnotationType = "comment"; AppCollection coll = AppService.GetCollection(entryId); AnnotationState state = AnnotateService.GetAnnotationState(coll, entryId); if (state != AnnotationState.On) throw new AnnotationNotAllowedException(entryId.ToString(), entry.AnnotationType, "the state is " + state); //default title to comment when not given if (entry.Title == null || string.IsNullOrEmpty(entry.Title.Text)) entry.Title = new AtomText(Atom.AtomNs + "title") { Text = "Comment" }; //approved? if (!AuthorizeService.IsAuthorized((User)System.Threading.Thread.CurrentPrincipal.Identity, entry.Id.ToScope(), AuthAction.ApproveAnnotation)) { entry.Control = new AppControl() { Approved = false }; } //clean input if (entry.Content.Type == "html" || entry.Content.Type == "xhtml") { if (AuthorizeService.IsAuthorized((User)System.Threading.Thread.CurrentPrincipal.Identity, entryId.ToScope(), AuthAction.ApproveAnnotation)) CleanContentService.CleanContentTrusted(entry.Content); else CleanContentService.CleanContentFully(entry.Content); } else if (entry.Content.Type == "text") { entry.Content.Text = entry.Content.Text.Replace("<", "<").Replace(">", ">"); } else if (entry.Content.Src == null) throw new AnnotationNotAllowedException(entryId.ToString(), entry.AnnotationType, "content must be text, html, or external."); AtomEntry parent = AtomEntryRepository.GetEntry(entryId); //check if there is already a content src annotation with this link int total; if (entry.IsExternal && AtomEntryRepository.GetEntries( new EntryCriteria() { EntryId = parent.Id, Annotations = true, Authorized = true, Deep = true }, 0, int.MaxValue, out total) .Where(a => a.Content.Src != null && a.Content.Src == entry.Content.Src).Count() > 0) throw new AnnotationNotAllowedException(parent.Id, entry.AnnotationType, "it already contains a link to the source."); //TODO: allow categories on annotations? entry.Categories = null; }