yavsc/web/Controllers/BlogsController.cs
Paul Schneider 948fc64ce1 Les activités
* BackOfficeController.cs: Impléménte un accès à l'API back office
  pour l'envoi d'une notification aux mobiles des cercles séléctionné
  de l'utilisateur

* NotifyEvent.aspx: Implemente un formulaire d'envoi d'une
  notification mobile

* NotifyEventResponse.aspx: initie une page de resultat à la
  notification mobile

* NpgsqlContentProvider.cs: reccupère la photo activité en base de
  données

* BlogsController.cs: En attendant mieux, les billets de blog sont
  noté par leur auteur, ou un admin.

* CalendarController.cs: Les fontions de notification GCM et de
  declaration d'enregistrement GCM
partent dans le controlleur back office.

* activity.sql: ajoute la photo activité dans la definition du modèle
  de données Npgsql

* style.css: La fonte de caractère "Open Sans" (Google fonts) pour le
  thème "clear"

* style.css: La fonte de caractère "Open Sans" (Google fonts) pour le
  thème "dark" aussi

* style.css: pas de fonte de caractère dans la feuille de style
  basique.

* BackOfficeController.cs: Impléménte un accès web back office pour
  l'envoi d'une notification aux mobiles des cercles séléctionné de
  l'utilisateur

* BlogsController.cs: Fixe la page de garde du blogspot en cas
  d'absence
de billet à publier publiquement.

* FrontOfficeController.cs: la fontion booking est maintenant censée
  conerner uniquement une activité,
dont le code APE est donné en dernière partie de la route de l'Url, ou
  en argument `id`.

* HomeController.cs: La page d'accueil présente maintenant les
  activités mises en oeuvre par au moins un utilisateur enregistré,
  validé et non vérouillé.
Le titre de l'activité est un lien vers la methode de reservation
  simple.

* GoogleHelpers.cs: recoit l'implementation de la methode de
  notification mobile

* SimpleJsonPostMethod.cs: Fixe l'envoi en UTF-8

* App.master: fonte de caractère pour le lien vers "Vos billets"

* parallax.js: fixe la différence de traitement entre l'horizontale et
  la verticale

* Profile.aspx: ajoute le sommaire de la validation

* Index.aspx: initie un index pour le back office

* Activities.aspx: nettoye la console de log javascript

* Booking.aspx: ajoute le champ caché au formulaire de resa

* Index.aspx: affiche les services fournis sur le site, par des
  utilisateur enregistrés validés non bloqué.

* Web.config: rends l'id Google d'enregistrement GCM accessible au
  utilisateurs anonymes,
qui voudraient commander ou interagir avec l'application, sans avoir à
  créer de compte sur le site.

* Web.csproj: ajoute le contrôleur du back office, et le formulaire de
  notification mobile

* EventPub.cs:
* BaseEvent.cs: internationalise l'évennement (la base d'une
  notification)

* YaEvent.cs: les champs fournisseur d'une notification ne sont pas
  requis. On peut en avoir de la part du site lui même, qui ne soient
  pas à l'origine d'un evennement tiers du workflow. Dans tous les
  autres cas, ils devraient être renseignés ... à suivre.

* Circle.cs:
* CircleBase.cs: ajoute une methode de construition des destinataires
  à partir d'un tableau d'identifiants de cercles.

* Activity.cs: implémente la photo activité dans le modèle

* SimpleBookingQuery.cs: refabriqué

* MessageWithPayLoad.cs: accuse aussi le champ `to` en cas d'absence
  de destinataire.

* LocalizedText.resx:
* LocalizedText.fr.resx:
* LocalizedText.Designer.cs:
* LocalizedText.fr.Designer.cs: internationalisation
2015-11-26 11:52:06 +01:00

412 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Runtime.Serialization.Formatters.Binary;
using System.Web;
using System.Web.Configuration;
using System.Web.Profile;
using System.Web.Security;
using Npgsql.Web.Blog;
using Yavsc;
using Yavsc.Model;
using Yavsc.Model.Blogs;
using Yavsc.ApiControllers;
using Yavsc.Model.RolesAndMembers;
using System.Net;
using System.Web.Mvc;
using Yavsc.Model.Circles;
using Yavsc.Helpers;
namespace Yavsc.Controllers
{
/// <summary>
/// Blogs controller.
/// </summary>
public class BlogsController : Controller
{
private string sitename =
WebConfigurationManager.AppSettings ["Name"];
/// <summary>
/// Index the specified title, pageIndex and pageSize.
/// </summary>
/// <param name="title">Title.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
public ActionResult Index (string title, int pageIndex = 0, int pageSize = 10)
{
if (title != null)
return Title (title, pageIndex, pageSize);
return BlogList (pageIndex, pageSize);
}
/// <summary>
/// Chooses the media.
/// </summary>
/// <returns>The media.</returns>
/// <param name="id">Identifier.</param>
public ActionResult ChooseMedia(long postid)
{
return View ();
}
/// <summary>
/// Blogs the list.
/// </summary>
/// <returns>The list.</returns>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
public ActionResult BlogList (int pageIndex = 0, int pageSize = 10)
{
int totalRecords;
var bs = BlogManager.LastPosts (pageIndex, pageSize, out totalRecords);
ViewData ["ResultCount"] = totalRecords;
ViewData ["PageSize"] = pageSize;
ViewData ["PageIndex"] = pageIndex;
var bec = new BlogEntryCollection (bs);
return View ("Index", bec );
}
/// <summary>
/// Title the specified title, pageIndex and pageSize.
/// </summary>
/// <param name="id">Title.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
[HttpGet]
public ActionResult Title (string title, int pageIndex = 0, int pageSize = 10)
{
int recordCount;
MembershipUser u = Membership.GetUser ();
string username = u == null ? null : u.UserName;
FindBlogEntryFlags sf = FindBlogEntryFlags.MatchTitle;
BlogEntryCollection c =
BlogManager.FindPost (username, title, sf, pageIndex, pageSize, out recordCount);
var utc = new UTBlogEntryCollection (title);
utc.AddRange (c);
ViewData ["ResultCount"] = recordCount;
ViewData ["PageIndex"] = pageIndex;
ViewData ["PageSize"] = pageSize;
return View ("Title", utc);
}
/// <summary>
/// Users the posts.
/// </summary>
/// <returns>The posts.</returns>
/// <param name="user">User.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
[HttpGet]
public ActionResult UserPosts (string user, string title=null, int pageIndex = 0, int pageSize = 10)
{
if (user == null)
return Index (title, pageSize, pageIndex);
if (title != null) return UserPost (user, title, pageIndex, pageSize);
int recordcount=0;
MembershipUser u = Membership.GetUser ();
FindBlogEntryFlags sf = FindBlogEntryFlags.MatchUserName;
ViewData ["SiteName"] = sitename;
ViewData ["BlogUser"] = user;
string readersName = null;
ViewData ["PageIndex"] = pageIndex;
ViewData ["pageSize"] = pageSize;
// displays invisible items when the logged user is also the author
if (u != null) {
if (u.UserName == user || Roles.IsUserInRole ("Admin"))
sf |= FindBlogEntryFlags.MatchInvisible;
readersName = u.UserName;
}
// find entries
BlogEntryCollection c =
BlogManager.FindPost (readersName, user, sf, pageIndex, pageSize, out recordcount);
// Get author's meta data
var pr = ProfileBase.Create (user);
if (pr != null) {
Profile bupr = new Profile (pr);
// listing meta data
ViewData ["BlogUserProfile"] = bupr;
ViewData ["BlogTitle"] = bupr.BlogTitle;
ViewData ["Avatar"] = bupr.avatar;
}
UUBlogEntryCollection uuc = new UUBlogEntryCollection (user, c);
ViewData ["ResultCount"] = recordcount;
ViewData ["PageIndex"] = pageIndex;
ViewData ["PageSize"] = pageSize;
return View ("UserPosts", uuc);
}
/// <summary>
/// Removes the comment.
/// </summary>
/// <returns>The comment.</returns>
/// <param name="cmtid">Cmtid.</param>
[Authorize(Roles="Blogger")]
public ActionResult RemoveComment (long cmtid)
{
long postid = BlogManager.RemoveComment (cmtid);
return GetPost (postid);
}
/// <summary>
/// Gets the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="postid">Postid.</param>
public ActionResult GetPost (long postid)
{
ViewData ["id"] = postid;
BlogEntry e = BlogManager.GetForReading (postid);
UUTBlogEntryCollection c = new UUTBlogEntryCollection (e.Author,e.Title);
c.Add (e);
ViewData ["user"] = c.Author;
ViewData ["title"] = c.Title;
Profile pr = new Profile (ProfileBase.Create (c.Author));
if (pr == null)
// the owner's profile must exist
// in order to publish its bills
return View ("NotAuthorized");
ViewData ["BlogUserProfile"] = pr;
ViewData ["Avatar"] = pr.avatar;
ViewData ["BlogTitle"] = pr.BlogTitle;
return View ("UserPost",c);
}
/// <summary>
/// Users the post.
/// Assume that :
/// * bec.Count > O
/// * bec.All(x=>x.Author == bec[0].Author) ;
/// </summary>
/// <returns>The post.</returns>
/// <param name="bec">Bec.</param>
private ActionResult UserPost (UUTBlogEntryCollection bec)
{
if (ModelState.IsValid)
if (bec.Count > 0) {
Profile pr = new Profile (ProfileBase.Create (bec.Author));
if (pr == null)
// the owner's profile must exist
// in order to publish its bills
// This should'nt occur, as long as
// a profile must exist for each one of
// existing user record in data base
// and each post is deleted with user deletion
// a post => an author => a profile
throw new Exception("Unexpected error retreiving author's profile");
ViewData ["BlogUserProfile"] = pr;
ViewData ["Avatar"] = pr.avatar;
ViewData ["BlogTitle"] = pr.BlogTitle;
MembershipUser u = Membership.GetUser ();
ViewData ["Author"] = bec.Author;
if (!pr.BlogVisible) {
// only deliver to admins or owner
if (u == null)
return View ("NotAuthorized");
else {
if (u.UserName != bec.Author)
if (!Roles.IsUserInRole (u.UserName, "Admin"))
return View ("NotAuthorized");
}
}
if (u == null || (u.UserName != bec.Author) && !Roles.IsUserInRole (u.UserName, "Admin")) {
// Filer on allowed posts
BlogEntryCollection filtered = bec.FilterFor((u == null)?null : u.UserName);
UUTBlogEntryCollection nbec = new UUTBlogEntryCollection (bec.Author, bec.Title);
nbec.AddRange (filtered);
View ("UserPost",nbec);
}
}
return View ("UserPost",bec);
}
/// <summary>
/// Users the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="user">User.</param>
/// <param name="title">Title.</param>
/// <param name="pageIndex">Page index.</param>
/// <param name="pageSize">Page size.</param>
public ActionResult UserPost (string user, string title, int pageIndex = 0, int pageSize = 10)
{
ViewData ["user"] = user;
ViewData ["title"] = title;
ViewData ["PageIndex"] = pageIndex;
ViewData ["pageSize"] = pageSize;
var pb = ProfileBase.Create (user);
if (pb == null)
// the owner's profile must exist
// in order to publish its bills
return View ("NotAuthorized");
Profile pr = new Profile (pb);
ViewData ["BlogUserProfile"] = pr;
ViewData ["Avatar"] = pr.avatar;
ViewData ["BlogTitle"] = pr.BlogTitle;
UUTBlogEntryCollection c = new UUTBlogEntryCollection (user, title);
c.AddRange ( BlogManager.FilterOnReadAccess (BlogManager.GetPost (user, title)));
return View ("UserPost",c);
}
/// <summary>
/// Post the specified title.
/// </summary>
/// <param name="title">Title.</param>
[Authorize(Roles="Blogger")]
public ActionResult Post (string title)
{
string un = Membership.GetUser ().UserName;
if (String.IsNullOrEmpty (title))
title = "";
ViewData ["SiteName"] = sitename;
ViewData ["Author"] = un;
ViewData ["AllowedCircles"] = CircleManager.DefaultProvider.List (un)
.Select (x => new SelectListItem {
Value = x.Id.ToString(),
Text = x.Title
});
return View ("Edit", new BlogEntry { Title = title, Author = un });
}
/// <summary>
/// Validates the edit.
/// </summary>
/// <returns>The edit.</returns>
/// <param name="model">Model.</param>
[Authorize(Roles="")]
public ActionResult Edit (BlogEntry model)
{
ViewData ["SiteName"] = sitename;
ViewData ["Author"] = Membership.GetUser ().UserName;
if (ModelState.IsValid) {
if (model.Id != 0) {
// ensures rights to update
BlogManager.GetForEditing (model.Id, true);
BlogManager.UpdatePost (model.Id, model.Title, model.Content, model.Visible, model.AllowedCircles);
YavscHelpers.Notify (ViewData, LocalizedText.BillUpdated);
} else {
model.Id = BlogManager.Post (model.Author, model.Title, model.Content, model.Visible, model.AllowedCircles);
YavscHelpers.Notify (ViewData, LocalizedText.BillCreated);
}
BlogManager.UpdatePostPhoto (model.Id, model.Photo);
}
ViewData ["AllowedCircles"] =
CircleManager.DefaultProvider.List (
Membership.GetUser ().UserName).Select (x => new SelectListItem {
Value = x.Id.ToString(),
Text = x.Title,
Selected = model.AllowedCircles.Contains (x.Id)
});
return View ("Edit", model);
}
/// <summary>
/// Edit the specified bill
/// </summary>
/// <param name="id">Identifier.</param>
[Authorize(Roles="Blogger")]
public ActionResult EditId (long postid)
{
BlogEntry e = BlogManager.GetForEditing (postid);
string user = Membership.GetUser ().UserName;
Profile pr = new Profile (ProfileBase.Create(e.Author));
ViewData ["BlogTitle"] = pr.BlogTitle;
ViewData ["LOGIN"] = user;
ViewData ["Id"] = postid;
// Populates the circles combo items
if (e.AllowedCircles == null)
e.AllowedCircles = new long[0];
ViewData ["AllowedCircles"] =
CircleManager.DefaultProvider.List (
Membership.GetUser ().UserName).Select (x => new SelectListItem {
Value = x.Id.ToString(),
Text = x.Title,
Selected = e.AllowedCircles.Contains (x.Id)
});
return View ("Edit",e);
}
/// <summary>
/// Comment the specified model.
/// </summary>
/// <param name="model">Model.</param>
[Authorize]
public ActionResult Comment (Comment model)
{
string username = Membership.GetUser ().UserName;
ViewData ["SiteName"] = sitename;
if (ModelState.IsValid) {
BlogManager.Comment (username, model.PostId, model.CommentText, model.Visible);
return GetPost (model.PostId);
}
return GetPost (model.PostId);
}
/// <summary>
/// Remove the specified blog entry, by its author and title,
/// using returnUrl as the URL to return to,
/// and confirm as a proof you really know what you do.
/// </summary>
/// <param name="id">Title.</param>
/// <param name="user">User.</param>
/// <param name="returnUrl">Return URL.</param>
/// <param name="confirm">If set to <c>true</c> confirm.</param>
[Authorize(Roles="Blogger")]
public ActionResult RemoveTitle (string user, string title, string returnUrl, bool confirm = false)
{
if (returnUrl == null)
if (Request.UrlReferrer != null)
returnUrl = Request.UrlReferrer.AbsoluteUri;
ViewData ["returnUrl"] = returnUrl;
ViewData ["Author"] = user;
ViewData ["Title"] = title;
if (Membership.GetUser ().UserName != user)
if (!Roles.IsUserInRole("Admin"))
throw new AuthorizationDenied (user);
if (!confirm)
return View ("RemoveTitle");
BlogManager.RemoveTitle (user, title);
if (returnUrl == null)
RedirectToAction ("Index", new { user = user });
return Redirect (returnUrl);
}
/// <summary>
/// Removes the post.
/// </summary>
/// <returns>The post.</returns>
/// <param name="id">Identifier.</param>
/// <param name="returnUrl">Return URL.</param>
/// <param name="confirm">If set to <c>true</c> confirm.</param>
[Authorize(Roles="Blogger")]
public ActionResult RemovePost (long postid, string returnUrl, bool confirm = false)
{
// ensures the access control
BlogEntry e = BlogManager.GetForEditing (postid);
if (e == null)
return new HttpNotFoundResult ("post id "+postid.ToString());
ViewData ["id"] = postid;
ViewData ["returnUrl"] = string.IsNullOrWhiteSpace(returnUrl)?
Request.UrlReferrer.AbsoluteUri.ToString(): returnUrl;
// TODO: cleaner way to disallow deletion
if (!confirm)
return View ("RemovePost",e);
BlogManager.RemovePost (postid);
if (string.IsNullOrWhiteSpace(returnUrl))
return RedirectToAction ("Index");
return Redirect (returnUrl);
}
}
}