permission handling
This commit is contained in:
parent
3495523bd4
commit
71262647b3
27 changed files with 243 additions and 288 deletions
|
|
@ -25,9 +25,10 @@ namespace Yavsc.Controllers
|
||||||
|
|
||||||
// GET: api/BlogApi
|
// GET: api/BlogApi
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IEnumerable<BlogPost> GetBlogspot()
|
public IEnumerable<BlogPost> GetBlogspot(int start=0, int take=25)
|
||||||
{
|
{
|
||||||
return _context.BlogSpot.Where(b => b.Visible).OrderByDescending(b => b.UserModified);
|
return _context.BlogSpot.OrderByDescending(b => b.UserModified)
|
||||||
|
.Skip(start).Take(take);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: api/BlogApi/5
|
// GET: api/BlogApi/5
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace Yavsc.ApiControllers
|
||||||
{
|
{
|
||||||
var bill = await billingService.GetBillAsync(billingCode, id);
|
var bill = await billingService.GetBillAsync(billingCode, id);
|
||||||
|
|
||||||
if ( authorizationService.AuthorizeAsync(User, bill, new ViewRequirement()).IsFaulted)
|
if ( authorizationService.AuthorizeAsync(User, bill, new ReadPermission()).IsFaulted)
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ namespace Yavsc.ApiControllers
|
||||||
}
|
}
|
||||||
logger.LogTrace(JsonConvert.SerializeObject(bill));
|
logger.LogTrace(JsonConvert.SerializeObject(bill));
|
||||||
|
|
||||||
if (!(await authorizationService.AuthorizeAsync(User, bill, new ViewRequirement())).Succeeded)
|
if (!(await authorizationService.AuthorizeAsync(User, bill, new ReadPermission())).Succeeded)
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +107,7 @@ namespace Yavsc.ApiControllers
|
||||||
.FirstOrDefault(e=>e.Id == id);
|
.FirstOrDefault(e=>e.Id == id);
|
||||||
if (estimate == null)
|
if (estimate == null)
|
||||||
return new BadRequestResult();
|
return new BadRequestResult();
|
||||||
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement())).Succeeded)
|
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ReadPermission())).Succeeded)
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -135,7 +135,7 @@ namespace Yavsc.ApiControllers
|
||||||
{
|
{
|
||||||
// For authorization purpose
|
// For authorization purpose
|
||||||
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
||||||
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement())).Succeeded)
|
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ReadPermission())).Succeeded)
|
||||||
|
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
|
|
@ -154,7 +154,7 @@ namespace Yavsc.ApiControllers
|
||||||
var estimate = dbContext.Estimates.Include( e=>e.Query
|
var estimate = dbContext.Estimates.Include( e=>e.Query
|
||||||
).Include(e=>e.Owner).Include(e=>e.Owner.Performer).Include(e=>e.Client)
|
).Include(e=>e.Owner).Include(e=>e.Owner.Performer).Include(e=>e.Client)
|
||||||
.FirstOrDefault( e=> e.Id == id && e.Query.ClientId == uid );
|
.FirstOrDefault( e=> e.Id == id && e.Query.ClientId == uid );
|
||||||
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement())).Succeeded)
|
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ReadPermission())).Succeeded)
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +171,7 @@ namespace Yavsc.ApiControllers
|
||||||
{
|
{
|
||||||
// For authorization purpose
|
// For authorization purpose
|
||||||
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
var estimate = dbContext.Estimates.FirstOrDefault(e=>e.Id == id);
|
||||||
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement())).Succeeded)
|
if (!(await authorizationService.AuthorizeAsync(User, estimate, new ReadPermission())).Succeeded)
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,14 @@
|
||||||
|
|
||||||
namespace Yavsc
|
namespace Yavsc
|
||||||
{
|
{
|
||||||
public interface IBlogPost : ITrackedEntity, IIdentified<long>, ITitle
|
public interface IBlogPostPayLoad
|
||||||
{
|
{
|
||||||
string AuthorId { get; set; }
|
|
||||||
string Content { get; set; }
|
string Content { get; set; }
|
||||||
string Photo { get; set; }
|
string Photo { get; set; }
|
||||||
bool Visible { get; set; }
|
|
||||||
|
}
|
||||||
|
public interface IBlogPost :IBlogPostPayLoad, ITrackedEntity, IIdentified<long>, ITitle
|
||||||
|
{
|
||||||
|
string AuthorId { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Yavsc.Helpers
|
||||||
{
|
{
|
||||||
var userPosts = dbContext.BlogSpot.Include(
|
var userPosts = dbContext.BlogSpot.Include(
|
||||||
b => b.Author
|
b => b.Author
|
||||||
).Where(x => ((x.AuthorId == posterId) && (x.Visible))).ToArray();
|
).Where(x => ((x.AuthorId == posterId))).ToArray();
|
||||||
return userPosts;
|
return userPosts;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -42,8 +42,7 @@ namespace Yavsc.Helpers
|
||||||
return dbContext.BlogSpot.Include(
|
return dbContext.BlogSpot.Include(
|
||||||
b => b.Author
|
b => b.Author
|
||||||
).Include(p => p.ACL).Where(x => x.Author.Id == posterId &&
|
).Include(p => p.ACL).Where(x => x.Author.Id == posterId &&
|
||||||
(x.Visible &&
|
(x.ACL.Count == 0 || x.ACL.Any(a => readerCirclesMemberships.Contains(a.CircleId))));
|
||||||
(x.ACL.Count == 0 || x.ACL.Any(a => readerCirclesMemberships.Contains(a.CircleId)))));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,14 @@ namespace Yavsc.Models.Blog
|
||||||
{
|
{
|
||||||
[Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
[Display(Name="Identifiant du post")]
|
[Display(Name="Identifiant du post")]
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
|
|
||||||
[Display(Name="Identifiant de l'auteur")]
|
[Display(Name="Identifiant de l'auteur")]
|
||||||
[ForeignKey("Author")]
|
[ForeignKey("Author")]
|
||||||
public string AuthorId { get; set; }
|
public string AuthorId { get; set; }
|
||||||
|
|
||||||
[Display(Name="Auteur")]
|
[Display(Name="Auteur")]
|
||||||
public virtual ApplicationUser Author { set; get; }
|
public virtual ApplicationUser Author { set; get; }
|
||||||
|
|
||||||
|
|
||||||
[Display(Name="Date de création")]
|
[Display(Name="Date de création")]
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Yavsc.Models.Blog
|
||||||
}
|
}
|
||||||
|
|
||||||
[Display(Name="Créateur")]
|
[Display(Name="Créateur")]
|
||||||
public string UserCreated
|
public string UserCreated
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Yavsc.Models.Blog
|
||||||
}
|
}
|
||||||
|
|
||||||
[Display(Name="Utilisateur ayant modifé le dernier")]
|
[Display(Name="Utilisateur ayant modifé le dernier")]
|
||||||
public string UserModified
|
public string UserModified
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +68,7 @@ namespace Yavsc.Models.Blog
|
||||||
if (existent==null) Tags.Add(new BlogTag { PostId = Id, Tag = tag } );
|
if (existent==null) Tags.Add(new BlogTag { PostId = Id, Tag = tag } );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Detag(Tag tag)
|
public void DeTag(Tag tag)
|
||||||
{
|
{
|
||||||
var existent = Tags.SingleOrDefault(t => (( t.TagId == tag.Id) && t.PostId == Id));
|
var existent = Tags.SingleOrDefault(t => (( t.TagId == tag.Id) && t.PostId == Id));
|
||||||
if (existent!=null) Tags.Remove(existent);
|
if (existent!=null) Tags.Remove(existent);
|
||||||
|
|
@ -80,10 +80,10 @@ namespace Yavsc.Models.Blog
|
||||||
}
|
}
|
||||||
|
|
||||||
[InverseProperty("Post")]
|
[InverseProperty("Post")]
|
||||||
public virtual List<BlogTag> Tags { get; set; }
|
public virtual List<BlogTag> Tags { get; set; }
|
||||||
|
|
||||||
[InverseProperty("Post")]
|
[InverseProperty("Post")]
|
||||||
public virtual List<Comment> Comments { get; set; }
|
public virtual List<Comment> Comments { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string OwnerId => AuthorId;
|
public string OwnerId => AuthorId;
|
||||||
|
|
|
||||||
12
src/Yavsc.Server/ViewModels/Auth/DeletePermission.cs
Normal file
12
src/Yavsc.Server/ViewModels/Auth/DeletePermission.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace Yavsc.ViewModels.Auth
|
||||||
|
{
|
||||||
|
public class DeletePermission: IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
public DeletePermission()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
src/Yavsc.Server/ViewModels/Auth/EditPermission.cs
Normal file
12
src/Yavsc.Server/ViewModels/Auth/EditPermission.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace Yavsc.ViewModels.Auth
|
||||||
|
{
|
||||||
|
public class EditPermission : IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
public EditPermission()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
|
|
||||||
namespace Yavsc.ViewModels.Auth
|
|
||||||
{
|
|
||||||
public class EditPermission : IAuthorizationRequirement
|
|
||||||
{
|
|
||||||
public EditPermission()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ReadPermission: IAuthorizationRequirement
|
|
||||||
{
|
|
||||||
public ReadPermission()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DeletePermission: IAuthorizationRequirement
|
|
||||||
{
|
|
||||||
public DeletePermission()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -2,10 +2,11 @@ using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Yavsc.ViewModels.Auth
|
namespace Yavsc.ViewModels.Auth
|
||||||
{
|
{
|
||||||
public class ViewRequirement : IAuthorizationRequirement
|
public class ReadPermission: IAuthorizationRequirement
|
||||||
{
|
{
|
||||||
public ViewRequirement()
|
public ReadPermission()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
11
src/Yavsc.Server/ViewModels/BlogSpot/BlogPostEdit.cs
Normal file
11
src/Yavsc.Server/ViewModels/BlogSpot/BlogPostEdit.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Yavsc.ViewModels.Blog;
|
||||||
|
|
||||||
|
public class BlogPostEditViewModel : BlogPostInputViewModel
|
||||||
|
{
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
|
||||||
|
public required long Id { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -8,19 +8,18 @@ namespace Yavsc.ViewModels.Blog
|
||||||
public class BlogPostInputViewModel
|
public class BlogPostInputViewModel
|
||||||
{
|
{
|
||||||
[StringLength(1024)]
|
[StringLength(1024)]
|
||||||
public string? Photo { get; set; }
|
public string? Photo { get; set; }
|
||||||
|
|
||||||
[StringLength(1024)]
|
[StringLength(1024)]
|
||||||
public required string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
[StringLength(56224)]
|
[StringLength(56224)]
|
||||||
public required string Content { get; set; }
|
public string Content { get; set; }
|
||||||
|
|
||||||
public bool Visible { get; set; }
|
|
||||||
|
|
||||||
[InverseProperty("Target")]
|
[InverseProperty("Target")]
|
||||||
[Display(Name="Liste de contrôle d'accès")]
|
[Display(Name="Liste de contrôle d'accès")]
|
||||||
public virtual List<CircleAuthorizationToBlogPost>? ACL { get; set; }
|
public virtual List<CircleAuthorizationToBlogPost>? ACL { get; set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Yavsc.ViewModels.BlogSpot
|
|
||||||
{
|
|
||||||
public class NewPost
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public string Title{ get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string Content { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -43,12 +43,44 @@ namespace Yavsc.Controllers
|
||||||
|
|
||||||
// GET: Blog
|
// GET: Blog
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<IActionResult> Index(string id)
|
public async Task<IActionResult> Index(string id, int skip=0, int take=25)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(id)) {
|
if (!string.IsNullOrEmpty(id)) {
|
||||||
return View("UserPosts", await UserPosts(id));
|
return View("UserPosts", await UserPosts(id));
|
||||||
}
|
}
|
||||||
return View();
|
IEnumerable<BlogPost> posts;
|
||||||
|
|
||||||
|
if (User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
string viewerId = User.GetUserId();
|
||||||
|
long[] usercircles = await _context.Circle.Include(c=>c.Members).
|
||||||
|
Where(c=>c.Members.Any(m=>m.MemberId == viewerId))
|
||||||
|
.Select(c=>c.Id).ToArrayAsync();
|
||||||
|
|
||||||
|
posts = _context.BlogSpot
|
||||||
|
.Include(b => b.Author)
|
||||||
|
.Include(p=>p.ACL)
|
||||||
|
.Include(p=>p.Tags)
|
||||||
|
.Include(p=>p.Comments)
|
||||||
|
.Where(p =>(p.ACL.Count == 0)
|
||||||
|
|| (p.AuthorId == viewerId)
|
||||||
|
|| (usercircles != null && p.ACL.Any(a => usercircles.Contains(a.CircleId)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
posts = _context.BlogSpot
|
||||||
|
.Include(b => b.Author)
|
||||||
|
.Include(p=>p.ACL)
|
||||||
|
.Include(p=>p.Tags)
|
||||||
|
.Include(p=>p.Comments)
|
||||||
|
.Where(p => p.ACL.Count == 0 ).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = posts.OrderByDescending( p=> p.DateCreated);
|
||||||
|
var grouped = data.GroupBy(p=> p.Title).Skip(skip).Take(take);
|
||||||
|
|
||||||
|
return View(grouped);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("~/Title/{id?}")]
|
[Route("~/Title/{id?}")]
|
||||||
|
|
@ -59,7 +91,7 @@ namespace Yavsc.Controllers
|
||||||
ViewData["Title"] = id;
|
ViewData["Title"] = id;
|
||||||
return View("Title", _context.BlogSpot.Include(
|
return View("Title", _context.BlogSpot.Include(
|
||||||
b => b.Author
|
b => b.Author
|
||||||
).Where(x => x.Title == id && (x.Visible || x.AuthorId == uid )).OrderByDescending(
|
).Where(x => x.Title == id && (x.AuthorId == uid )).OrderByDescending(
|
||||||
x => x.DateCreated
|
x => x.DateCreated
|
||||||
).ToList());
|
).ToList());
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +120,7 @@ namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
if ( _authorizationService.AuthorizeAsync(User, blog, new ViewRequirement()).IsFaulted)
|
if ( _authorizationService.AuthorizeAsync(User, blog, new ReadPermission()).IsFaulted)
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
@ -111,7 +143,8 @@ namespace Yavsc.Controllers
|
||||||
[Authorize()]
|
[Authorize()]
|
||||||
public IActionResult Create(string title)
|
public IActionResult Create(string title)
|
||||||
{
|
{
|
||||||
var result = new BlogPostInputViewModel{Title=title,Content=""};
|
var result = new BlogPostInputViewModel{Title=title
|
||||||
|
};
|
||||||
ViewData["PostTarget"]="Create";
|
ViewData["PostTarget"]="Create";
|
||||||
SetLangItems();
|
SetLangItems();
|
||||||
return View(result);
|
return View(result);
|
||||||
|
|
@ -168,7 +201,14 @@ namespace Yavsc.Controllers
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
SetLangItems();
|
SetLangItems();
|
||||||
return View(blog);
|
return View(new BlogPostEditViewModel
|
||||||
|
{
|
||||||
|
Id = blog.Id,
|
||||||
|
Title = blog.Title,
|
||||||
|
Content = blog.Content,
|
||||||
|
ACL = blog.ACL,
|
||||||
|
Photo = blog.Photo
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -179,27 +219,31 @@ namespace Yavsc.Controllers
|
||||||
// POST: Blog/Edit/5
|
// POST: Blog/Edit/5
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken,Authorize()]
|
[ValidateAntiForgeryToken,Authorize()]
|
||||||
public IActionResult Edit(BlogPost blog)
|
public async Task<IActionResult> Edit(BlogPostEditViewModel blogEdit)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var auth = _authorizationService.AuthorizeAsync(User, blog, new EditPermission());
|
var blog = _context.BlogSpot.SingleOrDefault(b=>b.Id == blogEdit.Id);
|
||||||
if (!auth.IsFaulted)
|
if (blog == null) {
|
||||||
{
|
ModelState.AddModelError("Id", "not found");
|
||||||
// saves the change
|
return View();
|
||||||
_context.Update(blog);
|
|
||||||
_context.SaveChanges(User.GetUserId());
|
|
||||||
ViewData["StatusMessage"] = "Post modified";
|
|
||||||
return RedirectToAction("Index");
|
|
||||||
}
|
}
|
||||||
else
|
if (!(await _authorizationService.AuthorizeAsync(User, blog, new EditPermission())).Succeeded) {
|
||||||
{
|
|
||||||
ViewData["StatusMessage"] = "Accès restreint";
|
ViewData["StatusMessage"] = "Accès restreint";
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
blog.Content=blogEdit.Content;
|
||||||
|
blog.Title = blogEdit.Title;
|
||||||
|
blog.Photo = blogEdit.Photo;
|
||||||
|
blog.ACL = blogEdit.ACL;
|
||||||
|
// saves the change
|
||||||
|
_context.Update(blog);
|
||||||
|
_context.SaveChanges(User.GetUserId());
|
||||||
|
ViewData["StatusMessage"] = "Post modified";
|
||||||
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
ViewData["PostTarget"]="Edit";
|
ViewData["PostTarget"]="Edit";
|
||||||
return View(blog);
|
return View(blogEdit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Blog/Delete/5
|
// GET: Blog/Delete/5
|
||||||
|
|
@ -223,12 +267,12 @@ namespace Yavsc.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: Blog/Delete/5
|
// POST: Blog/Delete/5
|
||||||
[HttpPost, ActionName("Delete"), Authorize()]
|
[HttpPost, ActionName("Delete"), Authorize("IsTheAuthor")]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public IActionResult DeleteConfirmed(long id)
|
public IActionResult DeleteConfirmed(long id)
|
||||||
{
|
{
|
||||||
var uid = User.GetUserId();
|
var uid = User.GetUserId();
|
||||||
BlogPost blog = _context.BlogSpot.Single(m => m.Id == id && m.AuthorId == uid );
|
BlogPost blog = _context.BlogSpot.Single(m => m.Id == id);
|
||||||
|
|
||||||
_context.BlogSpot.Remove(blog);
|
_context.BlogSpot.Remove(blog);
|
||||||
_context.SaveChanges(User.GetUserId());
|
_context.SaveChanges(User.GetUserId());
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
if (authorizationService.AuthorizeAsync(User, estimate, new ViewRequirement()).IsFaulted)
|
if (authorizationService.AuthorizeAsync(User, estimate, new ReadPermission()).IsFaulted)
|
||||||
{
|
{
|
||||||
return new ChallengeResult();
|
return new ChallengeResult();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ public static class HostingExtensions
|
||||||
services.AddDataProtection().PersistKeysToFileSystem(dataDir);
|
services.AddDataProtection().PersistKeysToFileSystem(dataDir);
|
||||||
AddYavscPolicies(services);
|
AddYavscPolicies(services);
|
||||||
|
|
||||||
services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
|
services.AddScoped<IAuthorizationHandler, PermissionHandler>();
|
||||||
|
|
||||||
|
|
||||||
AddAuthentication(builder);
|
AddAuthentication(builder);
|
||||||
|
|
@ -417,9 +417,8 @@ public static class HostingExtensions
|
||||||
var smtpSettings = services.GetRequiredService<IOptions<SmtpSettings>>();
|
var smtpSettings = services.GetRequiredService<IOptions<SmtpSettings>>();
|
||||||
var payPalSettings = services.GetRequiredService<IOptions<PayPalSettings>>();
|
var payPalSettings = services.GetRequiredService<IOptions<PayPalSettings>>();
|
||||||
var googleAuthSettings = services.GetRequiredService<IOptions<GoogleAuthSettings>>();
|
var googleAuthSettings = services.GetRequiredService<IOptions<GoogleAuthSettings>>();
|
||||||
var authorizationService = services.GetRequiredService<IAuthorizationService>();
|
|
||||||
var localization = services.GetRequiredService<IStringLocalizer<YavscLocalization>>();
|
var localization = services.GetRequiredService<IStringLocalizer<YavscLocalization>>();
|
||||||
Startup.Configure(app, siteSettings, smtpSettings, authorizationService,
|
Startup.Configure(app, siteSettings, smtpSettings,
|
||||||
payPalSettings, googleAuthSettings, localization, loggerFactory,
|
payPalSettings, googleAuthSettings, localization, loggerFactory,
|
||||||
app.Environment.EnvironmentName);
|
app.Environment.EnvironmentName);
|
||||||
app.ConfigureFileServerApp();
|
app.ConfigureFileServerApp();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,11 @@ public class PermissionHandler : IAuthorizationHandler
|
||||||
{
|
{
|
||||||
if (requirement is ReadPermission)
|
if (requirement is ReadPermission)
|
||||||
{
|
{
|
||||||
if (IsOwner(context.User, context.Resource)
|
if (IsPublic(context.Resource))
|
||||||
|
{
|
||||||
|
context.Succeed(requirement);
|
||||||
|
}
|
||||||
|
else if (IsOwner(context.User, context.Resource)
|
||||||
|| IsSponsor(context.User, context.Resource))
|
|| IsSponsor(context.User, context.Resource))
|
||||||
{
|
{
|
||||||
context.Succeed(requirement);
|
context.Succeed(requirement);
|
||||||
|
|
@ -41,6 +45,16 @@ public class PermissionHandler : IAuthorizationHandler
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsPublic(object? resource)
|
||||||
|
{
|
||||||
|
if (resource is BlogPost blogPost)
|
||||||
|
{
|
||||||
|
if (blogPost.ACL.Count==0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsOwner(ClaimsPrincipal user, object? resource)
|
private static bool IsOwner(ClaimsPrincipal user, object? resource)
|
||||||
{
|
{
|
||||||
if (resource is BlogPost blogPost)
|
if (resource is BlogPost blogPost)
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,7 @@ namespace Yavsc.Helpers
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "AsciiDocNet.TextLiteral":
|
case "AsciiDocNet.TextLiteral":
|
||||||
var tl = elt as TextLiteral;
|
RenderLitteral(elt, sb);
|
||||||
if (tl?.Attributes.Anchor!=null)
|
|
||||||
{
|
|
||||||
sb.AppendFormat("<a name=\"{0}\">{1}</a> ", tl.Attributes.Anchor.Id, tl.Attributes.Anchor.XRefLabel);
|
|
||||||
}
|
|
||||||
if (tl!=null) sb.Append(tl.Text);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "AsciiDocNet.Emphasis":
|
case "AsciiDocNet.Emphasis":
|
||||||
|
|
@ -114,27 +109,52 @@ namespace Yavsc.Helpers
|
||||||
sb.AppendHtml("</b>");
|
sb.AppendHtml("</b>");
|
||||||
break;
|
break;
|
||||||
case "AsciiDocNet.InternalAnchor":
|
case "AsciiDocNet.InternalAnchor":
|
||||||
InternalAnchor a = (InternalAnchor) elt;
|
InternalAnchor a = (InternalAnchor)elt;
|
||||||
sb.AppendFormat("<a name=\"{0}\">{1}</a> ", a.Id, a.XRefLabel);
|
sb.AppendFormat("<a name=\"{0}\">{1}</a> ", a.Id, a.XRefLabel);
|
||||||
break;
|
break;
|
||||||
case "AsciiDocNet.Subscript":
|
case "AsciiDocNet.Subscript":
|
||||||
sb.AppendHtml("<sup>");
|
sb.AppendHtml("<sup>");
|
||||||
Subscript sub = (Subscript)elt;
|
Subscript sub = (Subscript)elt;
|
||||||
sub.ToHtml(sb);
|
RenderLitteral(sub, sb);
|
||||||
sb.AppendHtml("</sup>");
|
sb.AppendHtml("</sup>");
|
||||||
break;
|
break;
|
||||||
case "AsciiDocNet.Superscript":
|
case "AsciiDocNet.Superscript":
|
||||||
sb.AppendHtml("<sup>");
|
sb.AppendHtml("<sup>");
|
||||||
Superscript sup = (Superscript)elt;
|
Superscript sup = (Superscript)elt;
|
||||||
sup.ToHtml(sb);
|
RenderLitteral(sup, sb);
|
||||||
sb.AppendHtml("</sup>");
|
sb.AppendHtml("</sup>");
|
||||||
break;
|
break;
|
||||||
|
case "AsciiDocNet.Mark":
|
||||||
|
sb.AppendHtml("<em>");
|
||||||
|
|
||||||
|
Mark mark = (Mark)elt;
|
||||||
|
if (mark.DoubleDelimited)
|
||||||
|
{
|
||||||
|
sb.AppendHtml("<b>");
|
||||||
|
RenderLitteral(mark, sb);
|
||||||
|
sb.AppendHtml("</b>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
RenderLitteral(mark, sb);
|
||||||
|
sb.AppendHtml("</em>");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
string unsupportedType = elt.GetType().FullName;
|
string unsupportedType = elt.GetType().FullName;
|
||||||
throw new InvalidProgramException(unsupportedType);
|
throw new InvalidProgramException(unsupportedType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RenderLitteral(IInlineElement elt, IHtmlContentBuilder sb)
|
||||||
|
{
|
||||||
|
var tl = elt as TextLiteral;
|
||||||
|
if (tl?.Attributes.Anchor != null)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("<a name=\"{0}\">{1}</a> ", tl.Attributes.Anchor.Id, tl.Attributes.Anchor.XRefLabel);
|
||||||
|
}
|
||||||
|
if (tl != null) sb.Append(tl.Text);
|
||||||
|
}
|
||||||
|
|
||||||
public static IHtmlContent ToHtml(this Document doc, int doclevel = 4)
|
public static IHtmlContent ToHtml(this Document doc, int doclevel = 4)
|
||||||
{
|
{
|
||||||
var contentbuilder = new HtmlContentBuilder();
|
var contentbuilder = new HtmlContentBuilder();
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ public class Startup
|
||||||
IApplicationBuilder app,
|
IApplicationBuilder app,
|
||||||
IOptions<SiteSettings> siteSettings,
|
IOptions<SiteSettings> siteSettings,
|
||||||
IOptions<SmtpSettings> smtpSettings,
|
IOptions<SmtpSettings> smtpSettings,
|
||||||
IAuthorizationService authorizationService,
|
|
||||||
IOptions<PayPalSettings> payPalSettings,
|
IOptions<PayPalSettings> payPalSettings,
|
||||||
IOptions<GoogleAuthSettings> googleSettings,
|
IOptions<GoogleAuthSettings> googleSettings,
|
||||||
IStringLocalizer<YavscLocalization> localizer,
|
IStringLocalizer<YavscLocalization> localizer,
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Yavsc.Models;
|
|
||||||
using Yavsc.Models.Blog;
|
|
||||||
using Yavsc.Helpers;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using IdentityServer8.Extensions;
|
|
||||||
|
|
||||||
namespace Yavsc.ViewComponents
|
|
||||||
{
|
|
||||||
public class BlogIndexViewComponent: ViewComponent
|
|
||||||
{
|
|
||||||
private readonly ApplicationDbContext _context;
|
|
||||||
|
|
||||||
public BlogIndexViewComponent(
|
|
||||||
ApplicationDbContext context)
|
|
||||||
{
|
|
||||||
_context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renders blog index ofr the specified user by name,
|
|
||||||
// grouped by title
|
|
||||||
public async Task<IViewComponentResult> InvokeAsync(int skip=0, int maxLen=25)
|
|
||||||
{
|
|
||||||
IEnumerable<BlogPost> posts;
|
|
||||||
|
|
||||||
if (User.IsAuthenticated())
|
|
||||||
{
|
|
||||||
string viewerId = UserClaimsPrincipal.GetUserId();
|
|
||||||
long[] usercircles = await _context.Circle.Include(c=>c.Members).
|
|
||||||
Where(c=>c.Members.Any(m=>m.MemberId == viewerId))
|
|
||||||
.Select(c=>c.Id).ToArrayAsync();
|
|
||||||
|
|
||||||
IQueryable<BlogPost> allposts = _context.BlogSpot
|
|
||||||
.Include(b => b.Author)
|
|
||||||
.Include(p=>p.ACL)
|
|
||||||
.Include(p=>p.Tags)
|
|
||||||
.Include(p=>p.Comments)
|
|
||||||
.Where(p => p.AuthorId == viewerId || p.Visible);
|
|
||||||
|
|
||||||
posts = (usercircles != null) ?
|
|
||||||
allposts.Where(p=> p.ACL.Count==0 || p.ACL.Any(a => usercircles.Contains(a.CircleId)))
|
|
||||||
: allposts.Where(p => p.ACL.Count == 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
posts = _context.BlogSpot
|
|
||||||
.Include(b => b.Author)
|
|
||||||
.Include(p=>p.ACL)
|
|
||||||
.Include(p=>p.Tags)
|
|
||||||
.Include(p=>p.Comments)
|
|
||||||
.Where(p => p.Visible && p.ACL.Count == 0 ).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = posts.OrderByDescending( p=> p.DateCreated);
|
|
||||||
var grouped = data.GroupBy(p=> p.Title).Skip(skip).Take(maxLen);
|
|
||||||
|
|
||||||
return View("Default", grouped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -56,12 +56,6 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="Visible" class="col-md-2 control-label"></label>
|
|
||||||
<div class="col-md-10">
|
|
||||||
<input asp-for="Visible" class="form-control"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="ACL" class="col-md-2 control-label"></label>
|
<label asp-for="ACL" class="col-md-2 control-label"></label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
<hr />
|
<hr />
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
<dt>
|
<dt>
|
||||||
Author"]
|
Author
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
@Model.Author
|
@Model.Author
|
||||||
|
|
@ -47,12 +47,6 @@
|
||||||
<dd>
|
<dd>
|
||||||
@Html.DisplayFor(model => model.Title)
|
@Html.DisplayFor(model => model.Title)
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
|
||||||
@Html.DisplayNameFor(model => model.Visible)
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
@Html.DisplayFor(model => model.Visible)
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<form asp-action="Delete">
|
<form asp-action="Delete">
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
@model Yavsc.ViewModels.Blog.BlogPostInputViewModel
|
@model BlogPostEditViewModel
|
||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Blog post edition";
|
ViewData["Title"] = "Blog post edition";
|
||||||
|
|
@ -58,11 +58,11 @@
|
||||||
<div title="Contenu du post" id="contentview">@Model.Content</div>
|
<div title="Contenu du post" id="contentview">@Model.Content</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<form>
|
<form asp-action="Edit">
|
||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||||
|
@Html.HiddenFor(m=>m.Id)
|
||||||
|
|
||||||
<div class="form-group mdcoding">
|
<div class="form-group mdcoding">
|
||||||
<label asp-for="Title" class="col-md-2 control-label"></label>
|
<label asp-for="Title" class="col-md-2 control-label"></label>
|
||||||
|
|
@ -90,12 +90,6 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="Visible" class="col-md-2 control-label"></label>
|
|
||||||
<div class="col-md-10">
|
|
||||||
<input asp-for="Visible" class="form-control"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="ACL" class="col-md-2 control-label"></label>
|
<label asp-for="ACL" class="col-md-2 control-label"></label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
|
|
@ -118,3 +112,4 @@
|
||||||
<a asp-action="Index">Back to List</a>
|
<a asp-action="Index">Back to List</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
using Yavsc.Migrations;
|
||||||
|
|
|
||||||
|
|
@ -45,5 +45,55 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@await Component.InvokeAsync("BlogIndex")
|
|
||||||
|
<table class="table">
|
||||||
|
@foreach (var group in Model) {
|
||||||
|
var title = group.Key ?? "@";
|
||||||
|
string secondclass="";
|
||||||
|
var first = group.First();
|
||||||
|
|
||||||
|
<tr><td colspan="3">
|
||||||
|
<a asp-action="Title" asp-route-id="@group.Key" >@title</a></td></tr>
|
||||||
|
@foreach (var item in group) {
|
||||||
|
var trunked = item.Content?.Length > 256;
|
||||||
|
<tr>
|
||||||
|
<td><a asp-action="Details" asp-route-id="@item.Id" class="bloglink">
|
||||||
|
<img src="@item.Photo" class="blogphoto"></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<asciidoc summary="256">@item.Content</asciidoc>
|
||||||
|
@if (trunked) { <a asp-action="Details" asp-route-id="@item.Id" class="bloglink">...</a> }
|
||||||
|
<span style="font-size:x-small;">@Html.DisplayFor(m => item.Author)</span>
|
||||||
|
<span style="font-size:xx-small;">
|
||||||
|
posté le @item.DateCreated.ToString("dddd d MMM yyyy à H:mm")
|
||||||
|
@if ((item.DateModified - item.DateCreated).Minutes > 0){
|
||||||
|
@:- Modifié le @item.DateModified.ToString("dddd d MMM yyyy à H:mm")
|
||||||
|
})
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul class="actiongroup">
|
||||||
|
@if ((await AuthorizationService.AuthorizeAsync(User, item, new ReadPermission())).Succeeded) {
|
||||||
|
<li>
|
||||||
|
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-lg">Details</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-lg">Details DEBUG</a>
|
||||||
|
}
|
||||||
|
@if ((await AuthorizationService.AuthorizeAsync(User, item, new EditPermission())).Succeeded) {
|
||||||
|
<li><a asp-action="Edit" asp-route-id="@item.Id" class="btn btn-default">Edit</a>
|
||||||
|
</li>
|
||||||
|
<li><a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-danger">Delete</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,15 @@
|
||||||
|
|
||||||
<h2 markdown="@ViewData["Title"]"></h2>
|
<h2 markdown="@ViewData["Title"]"></h2>
|
||||||
<p class="text-success">@ViewData["StatusMessage"]</p>
|
<p class="text-success">@ViewData["StatusMessage"]</p>
|
||||||
@if (User.IsSignedIn()) {
|
|
||||||
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="cbv" checked/>Invisibles, posts privés</label>
|
|
||||||
<script>
|
|
||||||
$("#cbv").change(function() {
|
|
||||||
if (this.checked) {
|
|
||||||
$("tr.hiddenpost").removeClass("hidden");
|
|
||||||
} else {
|
|
||||||
$("tr.hiddenpost").addClass("hidden");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
<p>
|
<p>
|
||||||
<a asp-action="Create" asp-route-title="@ViewData["Title"]">Poster au même titre"]</a>
|
<a asp-action="Create" asp-route-title="@ViewData["Title"]">Poster au même titre</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
|
||||||
@foreach (var item in Model) {
|
@foreach (var item in Model) {
|
||||||
var trclass = (item.Visible)?"visiblepost":"hiddenpost";
|
<tr>
|
||||||
|
|
||||||
<tr class="@trclass">
|
|
||||||
<td><a asp-action="Details" asp-route-id="@item.Id" class="bloglink">
|
<td><a asp-action="Details" asp-route-id="@item.Id" class="bloglink">
|
||||||
<img src="@item.Photo" class="blogphoto"></a>
|
<img src="@item.Photo" class="blogphoto"></a>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -41,7 +26,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul class="actiongroup">
|
<ul class="actiongroup">
|
||||||
@if ((await AuthorizationService.AuthorizeAsync(User, item, new ViewRequirement())).Succeeded) {
|
@if ((await AuthorizationService.AuthorizeAsync(User, item, new ReadPermission())).Succeeded) {
|
||||||
<li>
|
<li>
|
||||||
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-lg">Details</a>
|
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-lg">Details</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
Author"]
|
Author
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
@Html.DisplayNameFor(model => model.Content)
|
@Html.DisplayNameFor(model => model.Content)
|
||||||
|
|
@ -28,9 +28,6 @@
|
||||||
<th>
|
<th>
|
||||||
@Html.DisplayNameFor(model => model.Title)
|
@Html.DisplayNameFor(model => model.Title)
|
||||||
</th>
|
</th>
|
||||||
<th>
|
|
||||||
@Html.DisplayNameFor(model => model.Visible)
|
|
||||||
</th>
|
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
@ -56,9 +53,6 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@Html.DisplayFor(modelItem => item.Title)
|
@Html.DisplayFor(modelItem => item.Title)
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@Html.DisplayFor(modelItem => item.Visible)
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
@model IEnumerable<IGrouping<string,BlogPost>>
|
|
||||||
|
|
||||||
@if (User.IsSignedIn()) {
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="_cbv" checked/>Invisibles, posts privés</label>
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$('#_cbv').change(function()
|
|
||||||
{
|
|
||||||
if (this.checked) {
|
|
||||||
$('tr.hiddenpost').removeClass("hidden");
|
|
||||||
} else {
|
|
||||||
$('tr.hiddenpost').addClass("hidden");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
@foreach (var group in Model) {
|
|
||||||
var title = group.Key ?? "@";
|
|
||||||
string secondclass="";
|
|
||||||
var first = group.First();
|
|
||||||
string ftrclass = (first.Visible) ? "visiblepost" : "hiddenpost";
|
|
||||||
|
|
||||||
<tr><td colspan="3">
|
|
||||||
<a asp-action="Title" asp-route-id="@group.Key" >@title</a></td></tr>
|
|
||||||
@foreach (var item in group) {
|
|
||||||
var trclass = (item.Visible)?"visiblepost":"hiddenpost";
|
|
||||||
var trunked = item.Content?.Length > 256;
|
|
||||||
<tr class="@trclass">
|
|
||||||
<td><a asp-action="Details" asp-route-id="@item.Id" class="bloglink">
|
|
||||||
<img src="@item.Photo" class="blogphoto"></a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<asciidoc summary="256">@item.Content</asciidoc>
|
|
||||||
@if (trunked) { <a asp-action="Details" asp-route-id="@item.Id" class="bloglink">...</a> }
|
|
||||||
<span style="font-size:x-small;">@Html.DisplayFor(m => item.Author)</span>
|
|
||||||
<span style="font-size:xx-small;">
|
|
||||||
posté le @item.DateCreated.ToString("dddd d MMM yyyy à H:mm")
|
|
||||||
@if ((item.DateModified - item.DateCreated).Minutes > 0){
|
|
||||||
@:- Modifié le @item.DateModified.ToString("dddd d MMM yyyy à H:mm")
|
|
||||||
})
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul class="actiongroup">
|
|
||||||
@if ((await AuthorizationService.AuthorizeAsync(User, item, new ViewRequirement())).Succeeded) {
|
|
||||||
<li>
|
|
||||||
<a asp-action="Details" asp-route-id="@item.Id" class="btn btn-lg">Details</a>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
@if ((await AuthorizationService.AuthorizeAsync(User, item, new EditPermission())).Succeeded) {
|
|
||||||
<li><a asp-action="Edit" asp-route-id="@item.Id" class="btn btn-default">Edit</a>
|
|
||||||
</li>
|
|
||||||
<li><a asp-action="Delete" asp-route-id="@item.Id" class="btn btn-danger">Delete</a>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
@using Yavsc.Models.Access;
|
@using Yavsc.Models.Access;
|
||||||
@using Yavsc.Billing;
|
@using Yavsc.Billing;
|
||||||
@using Yavsc.Server.Models.Calendar;
|
@using Yavsc.Server.Models.Calendar;
|
||||||
|
@using Yavsc.ViewModels.Blog;
|
||||||
@using Yavsc.ViewModels.Haircut;
|
@using Yavsc.ViewModels.Haircut;
|
||||||
@using Yavsc.ViewModels.Administration;
|
@using Yavsc.ViewModels.Administration;
|
||||||
@using Yavsc.ViewModels.Account;
|
@using Yavsc.ViewModels.Account;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue