tout du bon:
- mobile app declaration (WIP) - login/logout depuis la même resource, sans bug (note: appliquer AllowAnonymous à la classe => methodes d'attribut Authorize non redirigées) - les médias des posts
This commit is contained in:
@ -1,16 +0,0 @@
|
|||||||
@model IEnumerable<blog>
|
|
||||||
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Blog spot";
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
@foreach (var entry in Model) {
|
|
||||||
<div class="col-md-3">
|
|
||||||
<h2> @entry.Title</h2>
|
|
||||||
<ul>
|
|
||||||
<li>Sample pages using ASP.NET MVC 6</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
@ -10,20 +10,20 @@
|
|||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
<h4>Blog</h4>
|
<h4>Blog</h4>
|
||||||
<hr />
|
<hr />
|
||||||
<div asp-validation-summary="ValidationSummary.ModelOnly" class="text-danger"></div>
|
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="title" class="col-md-2 control-label"></label>
|
<label asp-for="title" class="col-md-2 control-label"></label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<input asp-for="title" class="form-control" />
|
<input asp-for="title" class="form-control" />
|
||||||
<span asp-validation-for="title" class="text-danger" />
|
<span asp-validation-for="title" class="text-danger" ></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="photo" class="col-md-2 control-label"></label>
|
<label asp-for="photo" class="col-md-2 control-label"></label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<input asp-for="photo" class="form-control" />
|
<input asp-for="photo" class="form-control" />
|
||||||
<span asp-validation-for="photo" class="text-danger" />
|
<span asp-validation-for="photo" class="text-danger" ></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<textarea asp-for="bcontent" class="form-control" >
|
<textarea asp-for="bcontent" class="form-control" >
|
||||||
</textarea>
|
</textarea>
|
||||||
<span asp-validation-for="bcontent" class="text-danger" />
|
<span asp-validation-for="bcontent" class="text-danger" ></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -40,7 +40,6 @@
|
|||||||
<input asp-for="visible" class="form-control"/>
|
<input asp-for="visible" class="form-control"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@Html.Hidden("AuthorId")
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-md-offset-2 col-md-10">
|
<div class="col-md-offset-2 col-md-10">
|
||||||
<input type="submit" value="Create" class="btn btn-default" />
|
<input type="submit" value="Create" class="btn btn-default" />
|
||||||
|
@ -8,6 +8,18 @@
|
|||||||
<h4>Blog</h4>
|
<h4>Blog</h4>
|
||||||
<hr />
|
<hr />
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
|
<dt>
|
||||||
|
@Html.DisplayNameFor(model => model.title)
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
@Html.DisplayFor(model => model.title)
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
@Html.DisplayNameFor(model => model.photo)
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
@Html.DisplayFor(model => model.photo)
|
||||||
|
</dd>
|
||||||
<dt>
|
<dt>
|
||||||
@SR["Author"]
|
@SR["Author"]
|
||||||
</dt>
|
</dt>
|
||||||
@ -18,7 +30,7 @@
|
|||||||
Contenu
|
Contenu
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div markdown="@Model.bcontent" base="~/@Model.Author.UserName/@Model.Id"
|
<div markdown="@Model.bcontent" base="~/@Model.Id"
|
||||||
site="SiteSettings.Value"></div>
|
site="SiteSettings.Value"></div>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
<dt>
|
||||||
@ -27,12 +39,7 @@
|
|||||||
<dd>
|
<dd>
|
||||||
@Html.DisplayFor(model => model.modified)
|
@Html.DisplayFor(model => model.modified)
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
|
||||||
@Html.DisplayNameFor(model => model.photo)
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
@Html.DisplayFor(model => model.photo)
|
|
||||||
</dd>
|
|
||||||
<dt>
|
<dt>
|
||||||
@Html.DisplayNameFor(model => model.posted)
|
@Html.DisplayNameFor(model => model.posted)
|
||||||
</dt>
|
</dt>
|
||||||
@ -45,12 +52,7 @@
|
|||||||
<dd>
|
<dd>
|
||||||
@Html.DisplayFor(model => model.rate)
|
@Html.DisplayFor(model => model.rate)
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
|
||||||
@Html.DisplayNameFor(model => model.title)
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
@Html.DisplayFor(model => model.title)
|
|
||||||
</dd>
|
|
||||||
<dt>
|
<dt>
|
||||||
@Html.DisplayNameFor(model => model.visible)
|
@Html.DisplayNameFor(model => model.visible)
|
||||||
</dt>
|
</dt>
|
||||||
|
@ -182,8 +182,9 @@ editorcontenu.on('text-change',function(delta,source){
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
<div >
|
<div >
|
||||||
<form id="postfiles" class="dropzone" method="post" enctype="multipart/form-data">
|
<form id="postfiles" class="dropzone" method="post" enctype="multipart/form-data">
|
||||||
<div class="fallback">
|
<div class="fallback">
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
@item.Author?.UserName
|
@item.Author?.UserName
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@Html.DisplayFor(modelItem => item.title)
|
<markdown>@item.title</markdown>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@Html.DisplayFor(modelItem => item.modified)
|
@Html.DisplayFor(modelItem => item.modified)
|
||||||
|
@ -68,7 +68,6 @@
|
|||||||
@foreach (var description in Model.ExternalProviders) {
|
@foreach (var description in Model.ExternalProviders) {
|
||||||
<form action="/signin" method="post">
|
<form action="/signin" method="post">
|
||||||
<input type="hidden" name="Provider" value="@description.AuthenticationScheme" />
|
<input type="hidden" name="Provider" value="@description.AuthenticationScheme" />
|
||||||
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
|
||||||
<input type="hidden" name="AfterLoginRedirectUrl" value="@Model.AfterLoginRedirectUrl" />
|
<input type="hidden" name="AfterLoginRedirectUrl" value="@Model.AfterLoginRedirectUrl" />
|
||||||
<button class="btn btn-lg btn-success" type="submit">@SR["Connect using"] @description.DisplayName</button>
|
<button class="btn btn-lg btn-success" type="submit">@SR["Connect using"] @description.DisplayName</button>
|
||||||
@Html.AntiForgeryToken()
|
@Html.AntiForgeryToken()
|
||||||
|
@ -14,6 +14,7 @@ namespace Yavsc.WebApi.Controllers
|
|||||||
[Authorize,Route("~/api/account")]
|
[Authorize,Route("~/api/account")]
|
||||||
public class ApiAccountController : Controller
|
public class ApiAccountController : Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
private UserManager<ApplicationUser> _userManager;
|
private UserManager<ApplicationUser> _userManager;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
|
||||||
|
37
Yavsc/src/ApiController/GCMController.cs
Normal file
37
Yavsc/src/ApiController/GCMController.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Authorization;
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Yavsc.Models;
|
||||||
|
|
||||||
|
public class GCMController : Controller {
|
||||||
|
ILogger _logger;
|
||||||
|
ApplicationDbContext _context;
|
||||||
|
|
||||||
|
public GCMController (ApplicationDbContext context,
|
||||||
|
ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
_logger = loggerFactory.CreateLogger<GCMController>();
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
public void Register (GoogleCloudMobileDeclaration declaration)
|
||||||
|
{
|
||||||
|
if (_context.GCMDevices.Any(d => d.RegistrationId == declaration.RegistrationId))
|
||||||
|
{
|
||||||
|
var alreadyRegisteredDevice = _context.GCMDevices.FirstOrDefault(d => d.RegistrationId == declaration.RegistrationId);
|
||||||
|
// Assert alreadyRegisteredDevice != null
|
||||||
|
if (alreadyRegisteredDevice != declaration) {
|
||||||
|
_context.GCMDevices.Update(declaration);
|
||||||
|
_context.SaveChanges();
|
||||||
|
} // else nothing to do.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_context.GCMDevices.Add(declaration);
|
||||||
|
_context.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -70,10 +70,11 @@ public class BlogViewHandler : AuthorizationHandler<ViewRequirement, Blog>
|
|||||||
context.Succeed(requirement);
|
context.Succeed(requirement);
|
||||||
else if (context.User.Identity.IsAuthenticated)
|
else if (context.User.Identity.IsAuthenticated)
|
||||||
if (resource.AuthorId == context.User.GetUserId())
|
if (resource.AuthorId == context.User.GetUserId())
|
||||||
context.Succeed(requirement);
|
context.Succeed(requirement);
|
||||||
// TODO else if (resource.Circles && context.User belongs to
|
else if (resource.visible)
|
||||||
|
// TODO && ( resource.Circles == null || context.User belongs to resource.Circles )
|
||||||
|
context.Succeed(requirement);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CommandViewHandler : AuthorizationHandler<ViewRequirement, Command>
|
public class CommandViewHandler : AuthorizationHandler<ViewRequirement, Command>
|
||||||
@ -137,4 +138,6 @@ public class BlogViewHandler : AuthorizationHandler<ViewRequirement, Blog>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -24,8 +24,8 @@ namespace Yavsc
|
|||||||
public const string AdminGroupName = "Administrator";
|
public const string AdminGroupName = "Administrator";
|
||||||
public const string BlogModeratorGroupName = "Moderator";
|
public const string BlogModeratorGroupName = "Moderator";
|
||||||
public const string FrontOfficeGroupName = "FrontOffice";
|
public const string FrontOfficeGroupName = "FrontOffice";
|
||||||
public const string UserBlogFilesDir= "Blog";
|
|
||||||
public const string UserBillsFilesDir= "Bills";
|
public const string UserBillsFilesDir= "Bills";
|
||||||
|
public const string UserFilesDir = "UserFiles";
|
||||||
|
|
||||||
public const string GCMNotificationUrl = "https://gcm-http.googleapis.com/gcm/send";
|
public const string GCMNotificationUrl = "https://gcm-http.googleapis.com/gcm/send";
|
||||||
private static readonly string[] GoogleScopes = { "openid", "profile", "email" };
|
private static readonly string[] GoogleScopes = { "openid", "profile", "email" };
|
||||||
|
@ -18,8 +18,7 @@ using Yavsc.ViewModels.Account;
|
|||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
[AllowAnonymous]
|
[ServiceFilter(typeof(LanguageActionFilter)),AllowAnonymous]
|
||||||
[ServiceFilter(typeof(LanguageActionFilter))]
|
|
||||||
public class AccountController : Controller
|
public class AccountController : Controller
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
@ -138,6 +137,7 @@ namespace Yavsc.Controllers
|
|||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<IActionResult> LogOff(string returnUrl = null)
|
public async Task<IActionResult> LogOff(string returnUrl = null)
|
||||||
{
|
{
|
||||||
|
await HttpContext.Authentication.SignOutAsync("ServerCookie");
|
||||||
await _signInManager.SignOutAsync();
|
await _signInManager.SignOutAsync();
|
||||||
_logger.LogInformation(4, "User logged out.");
|
_logger.LogInformation(4, "User logged out.");
|
||||||
if (returnUrl==null) return RedirectToAction(nameof(HomeController.Index), "Home");
|
if (returnUrl==null) return RedirectToAction(nameof(HomeController.Index), "Home");
|
||||||
|
@ -14,8 +14,7 @@ using Microsoft.Extensions.OptionsModel;
|
|||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
[ServiceFilter(typeof(LanguageActionFilter)),
|
[ServiceFilter(typeof(LanguageActionFilter))]
|
||||||
AllowAnonymous]
|
|
||||||
public class BlogspotController : Controller
|
public class BlogspotController : Controller
|
||||||
{
|
{
|
||||||
ILogger _logger;
|
ILogger _logger;
|
||||||
@ -40,31 +39,30 @@ namespace Yavsc.Controllers
|
|||||||
public IActionResult Index(string id)
|
public IActionResult Index(string id)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(id))
|
if (!string.IsNullOrEmpty(id))
|
||||||
return UserPosts(id);
|
return UserPosts(id);
|
||||||
return View(_context.Blogspot.Include(
|
return View(_context.Blogspot.Include(
|
||||||
b=>b.Author
|
b => b.Author
|
||||||
).Where(p=>p.visible));
|
).Where(p => p.visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Title/{id?}")]
|
[Route("/Title/{id?}")]
|
||||||
public IActionResult Title(string id)
|
public IActionResult Title(string id)
|
||||||
{
|
{
|
||||||
return View("Index", _context.Blogspot.Include(
|
return View("Index", _context.Blogspot.Include(
|
||||||
b=>b.Author
|
b => b.Author
|
||||||
).Where(x=>x.title==id).ToList());
|
).Where(x => x.title == id).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Blog/{id?}")]
|
[Route("/Blog/{id?}")]
|
||||||
public IActionResult UserPosts(string id)
|
public IActionResult UserPosts(string id)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (User.IsSignedIn())
|
if (User.IsSignedIn())
|
||||||
return View("Index", _context.Blogspot.Include(
|
return View("Index", _context.Blogspot.Include(
|
||||||
b=>b.Author
|
b => b.Author
|
||||||
).Where(x=>x.Author.UserName==id).ToList());
|
).Where(x => x.Author.UserName == id).ToList());
|
||||||
return View("Index", _context.Blogspot.Include(
|
return View("Index", _context.Blogspot.Include(
|
||||||
b=>b.Author
|
b => b.Author
|
||||||
).Where(x=>x.Author.UserName==id && x.visible).ToList());
|
).Where(x => x.Author.UserName == id && x.visible).ToList());
|
||||||
}
|
}
|
||||||
// GET: Blog/Details/5
|
// GET: Blog/Details/5
|
||||||
public IActionResult Details(long? id)
|
public IActionResult Details(long? id)
|
||||||
@ -75,7 +73,7 @@ namespace Yavsc.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
Blog blog = _context.Blogspot.Include(
|
Blog blog = _context.Blogspot.Include(
|
||||||
b=>b.Author
|
b => b.Author
|
||||||
).Single(m => m.Id == id);
|
).Single(m => m.Id == id);
|
||||||
if (blog == null)
|
if (blog == null)
|
||||||
{
|
{
|
||||||
@ -86,19 +84,21 @@ namespace Yavsc.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GET: Blog/Create
|
// GET: Blog/Create
|
||||||
|
[Authorize("Authenticated")]
|
||||||
public IActionResult Create()
|
public IActionResult Create()
|
||||||
{
|
{
|
||||||
return View( new Blog { AuthorId = User.GetUserId() } );
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: Blog/Create
|
// POST: Blog/Create
|
||||||
[HttpPost]
|
[HttpPost, Authorize("Authenticated"), ValidateAntiForgeryToken]
|
||||||
[ValidateAntiForgeryToken,Authorize]
|
|
||||||
public IActionResult Create(Blog blog)
|
public IActionResult Create(Blog blog)
|
||||||
{
|
{
|
||||||
blog.modified = blog.posted = DateTime.Now;
|
blog.modified = blog.posted = DateTime.Now;
|
||||||
blog.rate = 0;
|
blog.rate = 0;
|
||||||
|
blog.AuthorId = User.GetUserId();
|
||||||
|
_logger.LogWarning($"Post from: {blog.AuthorId}");
|
||||||
|
ModelState.ClearValidationState("AuthorId");
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
blog.posted = DateTime.Now;
|
blog.posted = DateTime.Now;
|
||||||
@ -106,10 +106,10 @@ namespace Yavsc.Controllers
|
|||||||
_context.SaveChanges();
|
_context.SaveChanges();
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Invalid Blog entry ...");
|
_logger.LogWarning("Invalid Blog posted ...");
|
||||||
return View(blog);
|
return View(blog);
|
||||||
}
|
}
|
||||||
|
[Authorize("Authenticated")]
|
||||||
// GET: Blog/Edit/5
|
// GET: Blog/Edit/5
|
||||||
public async Task<IActionResult> Edit(long? id)
|
public async Task<IActionResult> Edit(long? id)
|
||||||
{
|
{
|
||||||
@ -118,7 +118,7 @@ namespace Yavsc.Controllers
|
|||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
Blog blog = _context.Blogspot.Include(x=>x.Author).Single(m => m.Id == id);
|
Blog blog = _context.Blogspot.Include(x => x.Author).Single(m => m.Id == id);
|
||||||
if (blog == null)
|
if (blog == null)
|
||||||
{
|
{
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
@ -135,7 +135,7 @@ namespace Yavsc.Controllers
|
|||||||
|
|
||||||
// POST: Blog/Edit/5
|
// POST: Blog/Edit/5
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken,Authorize("Authenticated")]
|
||||||
public IActionResult Edit(Blog blog)
|
public IActionResult Edit(Blog blog)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
@ -146,18 +146,19 @@ namespace Yavsc.Controllers
|
|||||||
blog.modified = DateTime.Now;
|
blog.modified = DateTime.Now;
|
||||||
_context.Update(blog);
|
_context.Update(blog);
|
||||||
_context.SaveChanges();
|
_context.SaveChanges();
|
||||||
ViewData["StatusMessage"]="Post modified";
|
ViewData["StatusMessage"] = "Post modified";
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
} // TODO Else hit me hard
|
} // TODO Else hit me hard
|
||||||
else {
|
else
|
||||||
ViewData["StatusMessage"]="Access denied ...";
|
{
|
||||||
|
ViewData["StatusMessage"] = "Access denied ...";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return View(blog);
|
return View(blog);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: Blog/Delete/5
|
// GET: Blog/Delete/5
|
||||||
[ActionName("Delete")]
|
[ActionName("Delete"),Authorize("Authenticated")]
|
||||||
public IActionResult Delete(long? id)
|
public IActionResult Delete(long? id)
|
||||||
{
|
{
|
||||||
if (id == null)
|
if (id == null)
|
||||||
@ -166,7 +167,7 @@ namespace Yavsc.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
Blog blog = _context.Blogspot.Include(
|
Blog blog = _context.Blogspot.Include(
|
||||||
b=>b.Author
|
b => b.Author
|
||||||
).Single(m => m.Id == id);
|
).Single(m => m.Id == id);
|
||||||
if (blog == null)
|
if (blog == null)
|
||||||
{
|
{
|
||||||
@ -177,13 +178,14 @@ namespace Yavsc.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// POST: Blog/Delete/5
|
// POST: Blog/Delete/5
|
||||||
[HttpPost, ActionName("Delete"), Authorize]
|
[HttpPost, ActionName("Delete"), Authorize("Authenticated")]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public IActionResult DeleteConfirmed(long id)
|
public IActionResult DeleteConfirmed(long id)
|
||||||
{
|
{
|
||||||
Blog blog = _context.Blogspot.Single(m => m.Id == id);
|
Blog blog = _context.Blogspot.Single(m => m.Id == id);
|
||||||
var auth = _authorizationService.AuthorizeAsync(User, blog, new EditRequirement());
|
var auth = _authorizationService.AuthorizeAsync(User, blog, new EditRequirement());
|
||||||
if (auth.Result) {
|
if (auth.Result)
|
||||||
|
{
|
||||||
_context.Blogspot.Remove(blog);
|
_context.Blogspot.Remove(blog);
|
||||||
_context.SaveChanges();
|
_context.SaveChanges();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ using Yavsc.Models.Booking;
|
|||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Controllers
|
||||||
{
|
{
|
||||||
[ServiceFilter(typeof(LanguageActionFilter)), AllowAnonymous,
|
[ServiceFilter(typeof(LanguageActionFilter)),
|
||||||
Route("do")]
|
Route("do")]
|
||||||
public class FrontOfficeController : Controller
|
public class FrontOfficeController : Controller
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ namespace Yavsc.Controllers
|
|||||||
ApplicationDbContext _context;
|
ApplicationDbContext _context;
|
||||||
UserManager<ApplicationUser> _userManager;
|
UserManager<ApplicationUser> _userManager;
|
||||||
|
|
||||||
ILogger _logger;
|
ILogger _logger;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
private TokenAuthOptions _tokenOptions;
|
private TokenAuthOptions _tokenOptions;
|
||||||
|
|
||||||
@ -46,13 +46,15 @@ ILogger _logger;
|
|||||||
|
|
||||||
|
|
||||||
[HttpGet("~/signin")]
|
[HttpGet("~/signin")]
|
||||||
public ActionResult SignIn(string returnUrl = null) {
|
public ActionResult SignIn(string returnUrl = null, string target = null)
|
||||||
|
{
|
||||||
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
||||||
// will be redirected to after a successful authentication and not
|
// will be redirected to after a successful authentication and not
|
||||||
// the redirect_uri of the requesting client application.
|
// the redirect_uri of the requesting client application.
|
||||||
return View("SignIn", new LoginViewModel
|
return View("SignIn", new LoginViewModel
|
||||||
{
|
{
|
||||||
ReturnUrl = returnUrl,
|
ReturnUrl = returnUrl,
|
||||||
|
AfterLoginRedirectUrl = target,
|
||||||
ExternalProviders = HttpContext.GetExternalProviders()
|
ExternalProviders = HttpContext.GetExternalProviders()
|
||||||
});
|
});
|
||||||
/* Note: When using an external login provider, redirect the query :
|
/* Note: When using an external login provider, redirect the query :
|
||||||
@ -61,49 +63,72 @@ ILogger _logger;
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("~/authenticate")]
|
||||||
|
public ActionResult Authenticate(string returnUrl = null)
|
||||||
|
{
|
||||||
|
return SignIn("/Account/ExternalLoginCallback",returnUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("~/forbidden")]
|
||||||
|
public ActionResult Forbidden(string returnUrl = null)
|
||||||
|
{
|
||||||
|
return SignIn("/Account/ExternalLoginCallback",returnUrl);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("~/signin")]
|
[HttpPost("~/signin")]
|
||||||
public IActionResult SignIn( string Provider, string ReturnUrl, string AfterLoginRedirectUrl) {
|
public IActionResult SignIn(string Provider, string ReturnUrl, string AfterLoginRedirectUrl)
|
||||||
|
{
|
||||||
// Note: the "provider" parameter corresponds to the external
|
// Note: the "provider" parameter corresponds to the external
|
||||||
// authentication provider choosen by the user agent.
|
// authentication provider choosen by the user agent.
|
||||||
if (string.IsNullOrEmpty(Provider)) {
|
if (string.IsNullOrEmpty(Provider))
|
||||||
|
{
|
||||||
_logger.LogWarning("Provider not specified");
|
_logger.LogWarning("Provider not specified");
|
||||||
return HttpBadRequest();
|
return HttpBadRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_signInManager.GetExternalAuthenticationSchemes().Any(x=>x.AuthenticationScheme==Provider)) {
|
if (!_signInManager.GetExternalAuthenticationSchemes().Any(x => x.AuthenticationScheme == Provider))
|
||||||
|
{
|
||||||
_logger.LogWarning($"Provider not found : {Provider}");
|
_logger.LogWarning($"Provider not found : {Provider}");
|
||||||
return HttpBadRequest();
|
return HttpBadRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
|
||||||
// will be redirected to after a successful authentication and not
|
|
||||||
// the redirect_uri of the requesting client application.
|
|
||||||
if (string.IsNullOrEmpty(ReturnUrl)) {
|
|
||||||
_logger.LogWarning("ReturnUrl not specified");
|
|
||||||
return HttpBadRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instruct the middleware corresponding to the requested external identity
|
// Instruct the middleware corresponding to the requested external identity
|
||||||
// provider to redirect the user agent to its own authorization endpoint.
|
// provider to redirect the user agent to its own authorization endpoint.
|
||||||
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
|
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
|
||||||
|
|
||||||
// If AfterLoginRedirectUrl is non null,
|
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
||||||
// This is a web interface access,
|
// will be redirected to after a successful authentication and not
|
||||||
// and the wanted redirection
|
// the redirect_uri of the requesting client application.
|
||||||
// after the successfull authentication
|
if (string.IsNullOrEmpty(ReturnUrl))
|
||||||
if (AfterLoginRedirectUrl!=null) {
|
{
|
||||||
ReturnUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = AfterLoginRedirectUrl });
|
|
||||||
|
// If AfterLoginRedirectUrl is non null,
|
||||||
|
// This is a web interface access,
|
||||||
|
/// Assert (model.ReturnUrl==null)
|
||||||
|
/// and the wanted redirection
|
||||||
|
// after the successfull authentication
|
||||||
|
if (AfterLoginRedirectUrl != null)
|
||||||
|
{
|
||||||
|
ReturnUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = AfterLoginRedirectUrl });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("ReturnUrl not specified");
|
||||||
|
return HttpBadRequest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(Provider, ReturnUrl);
|
var properties = _signInManager.ConfigureExternalAuthenticationProperties(Provider, ReturnUrl);
|
||||||
|
|
||||||
return new ChallengeResult(Provider, properties);
|
return new ChallengeResult(Provider, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("~/signout"), HttpPost("~/signout")]
|
[HttpGet("~/signout"), HttpPost("~/signout")]
|
||||||
public async Task SignOut() {
|
public async Task SignOut()
|
||||||
|
{
|
||||||
// Instruct the cookies middleware to delete the local cookie created
|
// Instruct the cookies middleware to delete the local cookie created
|
||||||
// when the user agent is redirected from the external identity provider
|
// when the user agent is redirected from the external identity provider
|
||||||
// after a successful authentication flow (e.g Google or Facebook).
|
// after a successful authentication flow (e.g Google or Facebook).
|
||||||
@ -132,23 +157,27 @@ ILogger _logger;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("~/connect/authorize"), HttpPost("~/connect/authorize")]
|
[HttpGet("~/connect/authorize"), HttpPost("~/connect/authorize")]
|
||||||
public async Task<IActionResult> Authorize(CancellationToken cancellationToken) {
|
public async Task<IActionResult> Authorize(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
// Note: when a fatal error occurs during the request processing, an OpenID Connect response
|
// Note: when a fatal error occurs during the request processing, an OpenID Connect response
|
||||||
// is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler.
|
// is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler.
|
||||||
// You can safely remove this part and let ASOS automatically handle the unrecoverable errors
|
// You can safely remove this part and let ASOS automatically handle the unrecoverable errors
|
||||||
// by switching ApplicationCanDisplayErrors to false in Startup.cs.
|
// by switching ApplicationCanDisplayErrors to false in Startup.cs.
|
||||||
var response = HttpContext.GetOpenIdConnectResponse();
|
var response = HttpContext.GetOpenIdConnectResponse();
|
||||||
if (response == null) {
|
if (response == null)
|
||||||
_logger.LogError("GetOpenIdConnectResponse is null");
|
{
|
||||||
|
_logger.LogError("GetOpenIdConnectResponse is null");
|
||||||
return View("OidcError", response);
|
return View("OidcError", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the authorization request from the ASP.NET environment.
|
// Extract the authorization request from the ASP.NET environment.
|
||||||
var request = HttpContext.GetOpenIdConnectRequest();
|
var request = HttpContext.GetOpenIdConnectRequest();
|
||||||
if (request == null) {
|
if (request == null)
|
||||||
_logger.LogError("An internal error has occurred, GetOpenIdConnectRequest is null");
|
{
|
||||||
return View("OidcError", new OpenIdConnectMessage {
|
_logger.LogError("An internal error has occurred, GetOpenIdConnectRequest is null");
|
||||||
|
return View("OidcError", new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = OpenIdConnectConstants.Errors.ServerError,
|
Error = OpenIdConnectConstants.Errors.ServerError,
|
||||||
ErrorDescription = "An internal error has occurred"
|
ErrorDescription = "An internal error has occurred"
|
||||||
});
|
});
|
||||||
@ -160,10 +189,13 @@ ILogger _logger;
|
|||||||
// To work around this limitation, the OpenID Connect request is automatically saved in the cache and will be
|
// To work around this limitation, the OpenID Connect request is automatically saved in the cache and will be
|
||||||
// restored by the OpenID Connect server middleware after the external authentication process has been completed.
|
// restored by the OpenID Connect server middleware after the external authentication process has been completed.
|
||||||
|
|
||||||
if (!User.Identities.Any(identity => identity.IsAuthenticated)) {
|
if (!User.Identities.Any(identity => identity.IsAuthenticated))
|
||||||
_logger.LogWarning("new ChallengeResult");
|
{
|
||||||
return new ChallengeResult(new AuthenticationProperties {
|
_logger.LogWarning("new ChallengeResult");
|
||||||
RedirectUri = Url.Action(nameof(Authorize), new {
|
return new ChallengeResult(new AuthenticationProperties
|
||||||
|
{
|
||||||
|
RedirectUri = Url.Action(nameof(Authorize), new
|
||||||
|
{
|
||||||
request_id = request.GetUniqueIdentifier()
|
request_id = request.GetUniqueIdentifier()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -174,9 +206,11 @@ ILogger _logger;
|
|||||||
// In theory, this null check shouldn't be needed, but a race condition could occur if you
|
// In theory, this null check shouldn't be needed, but a race condition could occur if you
|
||||||
// manually removed the application details from the database after the initial check made by ASOS.
|
// manually removed the application details from the database after the initial check made by ASOS.
|
||||||
var application = await GetApplicationAsync(request.ClientId, cancellationToken);
|
var application = await GetApplicationAsync(request.ClientId, cancellationToken);
|
||||||
if (application == null) {
|
if (application == null)
|
||||||
|
{
|
||||||
_logger.LogError("Details concerning the calling client application cannot be found in the database");
|
_logger.LogError("Details concerning the calling client application cannot be found in the database");
|
||||||
return View("OidcError", new OpenIdConnectMessage {
|
return View("OidcError", new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = OpenIdConnectConstants.Errors.InvalidClient,
|
Error = OpenIdConnectConstants.Errors.InvalidClient,
|
||||||
ErrorDescription = "Details concerning the calling client application cannot be found in the database"
|
ErrorDescription = "Details concerning the calling client application cannot be found in the database"
|
||||||
});
|
});
|
||||||
@ -187,15 +221,19 @@ ILogger _logger;
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize, HttpPost("~/connect/authorize/accept"), ValidateAntiForgeryToken]
|
[Authorize, HttpPost("~/connect/authorize/accept"), ValidateAntiForgeryToken]
|
||||||
public async Task<IActionResult> Accept(CancellationToken cancellationToken) {
|
public async Task<IActionResult> Accept(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
var response = HttpContext.GetOpenIdConnectResponse();
|
var response = HttpContext.GetOpenIdConnectResponse();
|
||||||
if (response != null) {
|
if (response != null)
|
||||||
|
{
|
||||||
return View("OidcError", response);
|
return View("OidcError", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = HttpContext.GetOpenIdConnectRequest();
|
var request = HttpContext.GetOpenIdConnectRequest();
|
||||||
if (request == null) {
|
if (request == null)
|
||||||
return View("OidcError", new OpenIdConnectMessage {
|
{
|
||||||
|
return View("OidcError", new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = OpenIdConnectConstants.Errors.ServerError,
|
Error = OpenIdConnectConstants.Errors.ServerError,
|
||||||
ErrorDescription = "An internal error has occurred"
|
ErrorDescription = "An internal error has occurred"
|
||||||
});
|
});
|
||||||
@ -207,7 +245,8 @@ ILogger _logger;
|
|||||||
|
|
||||||
// Copy the claims retrieved from the external identity provider
|
// Copy the claims retrieved from the external identity provider
|
||||||
// (e.g Google, Facebook, a WS-Fed provider or another OIDC server).
|
// (e.g Google, Facebook, a WS-Fed provider or another OIDC server).
|
||||||
foreach (var claim in HttpContext.User.Claims) {
|
foreach (var claim in HttpContext.User.Claims)
|
||||||
|
{
|
||||||
// Allow ClaimTypes.Name to be added in the id_token.
|
// Allow ClaimTypes.Name to be added in the id_token.
|
||||||
// ClaimTypes.NameIdentifier is automatically added, even if its
|
// ClaimTypes.NameIdentifier is automatically added, even if its
|
||||||
// destination is not defined or doesn't include "id_token".
|
// destination is not defined or doesn't include "id_token".
|
||||||
@ -218,7 +257,8 @@ ILogger _logger;
|
|||||||
OpenIdConnectConstants.Destinations.IdentityToken);
|
OpenIdConnectConstants.Destinations.IdentityToken);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (claim.Type == ClaimTypes.Name) {
|
if (claim.Type == ClaimTypes.Name)
|
||||||
|
{
|
||||||
claim.WithDestination("code");
|
claim.WithDestination("code");
|
||||||
claim.WithDestination("id_token");
|
claim.WithDestination("id_token");
|
||||||
}
|
}
|
||||||
@ -226,8 +266,10 @@ ILogger _logger;
|
|||||||
}
|
}
|
||||||
|
|
||||||
var application = await GetApplicationAsync(request.ClientId, cancellationToken);
|
var application = await GetApplicationAsync(request.ClientId, cancellationToken);
|
||||||
if (application == null) {
|
if (application == null)
|
||||||
return View("OidcError", new OpenIdConnectMessage {
|
{
|
||||||
|
return View("OidcError", new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = OpenIdConnectConstants.Errors.InvalidClient,
|
Error = OpenIdConnectConstants.Errors.InvalidClient,
|
||||||
ErrorDescription = "Details concerning the calling client application cannot be found in the database"
|
ErrorDescription = "Details concerning the calling client application cannot be found in the database"
|
||||||
});
|
});
|
||||||
@ -238,7 +280,7 @@ ILogger _logger;
|
|||||||
// the whole delegation chain from the resource server (see ResourceController.cs).
|
// the whole delegation chain from the resource server (see ResourceController.cs).
|
||||||
identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
|
identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
|
||||||
identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID);
|
identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID);
|
||||||
identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName,"code id_token");
|
identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName, "code id_token");
|
||||||
|
|
||||||
var properties = new AuthenticationProperties();
|
var properties = new AuthenticationProperties();
|
||||||
|
|
||||||
@ -271,15 +313,19 @@ ILogger _logger;
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize, HttpPost("~/connect/authorize/deny"), ValidateAntiForgeryToken]
|
[Authorize, HttpPost("~/connect/authorize/deny"), ValidateAntiForgeryToken]
|
||||||
public IActionResult Deny(CancellationToken cancellationToken) {
|
public IActionResult Deny(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
var response = HttpContext.GetOpenIdConnectResponse();
|
var response = HttpContext.GetOpenIdConnectResponse();
|
||||||
if (response != null) {
|
if (response != null)
|
||||||
|
{
|
||||||
return View("OidcError", response);
|
return View("OidcError", response);
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = HttpContext.GetOpenIdConnectRequest();
|
var request = HttpContext.GetOpenIdConnectRequest();
|
||||||
if (request == null) {
|
if (request == null)
|
||||||
return View("OidcError", new OpenIdConnectMessage {
|
{
|
||||||
|
return View("OidcError", new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = OpenIdConnectConstants.Errors.ServerError,
|
Error = OpenIdConnectConstants.Errors.ServerError,
|
||||||
ErrorDescription = "An internal error has occurred"
|
ErrorDescription = "An internal error has occurred"
|
||||||
});
|
});
|
||||||
@ -289,7 +335,8 @@ ILogger _logger;
|
|||||||
// Notify AspNet.Security.OpenIdConnect.Server that the authorization grant has been denied.
|
// Notify AspNet.Security.OpenIdConnect.Server that the authorization grant has been denied.
|
||||||
// Note: OpenIdConnectServerHandler will automatically take care of redirecting
|
// Note: OpenIdConnectServerHandler will automatically take care of redirecting
|
||||||
// the user agent to the client application using the appropriate response_mode.
|
// the user agent to the client application using the appropriate response_mode.
|
||||||
HttpContext.SetOpenIdConnectResponse(new OpenIdConnectMessage {
|
HttpContext.SetOpenIdConnectResponse(new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = "access_denied",
|
Error = "access_denied",
|
||||||
ErrorDescription = "The authorization grant has been denied by the resource owner",
|
ErrorDescription = "The authorization grant has been denied by the resource owner",
|
||||||
RedirectUri = request.RedirectUri,
|
RedirectUri = request.RedirectUri,
|
||||||
@ -301,9 +348,11 @@ ILogger _logger;
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("~/connect/logout")]
|
[HttpGet("~/connect/logout")]
|
||||||
public async Task<ActionResult> Logout() {
|
public async Task<ActionResult> Logout()
|
||||||
|
{
|
||||||
var response = HttpContext.GetOpenIdConnectResponse();
|
var response = HttpContext.GetOpenIdConnectResponse();
|
||||||
if (response != null) {
|
if (response != null)
|
||||||
|
{
|
||||||
_logger.LogError("GetOpenIdConnectResponse is null");
|
_logger.LogError("GetOpenIdConnectResponse is null");
|
||||||
return View("OidcError", response);
|
return View("OidcError", response);
|
||||||
}
|
}
|
||||||
@ -314,9 +363,11 @@ ILogger _logger;
|
|||||||
var identity = await HttpContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme);
|
var identity = await HttpContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme);
|
||||||
|
|
||||||
var request = HttpContext.GetOpenIdConnectRequest();
|
var request = HttpContext.GetOpenIdConnectRequest();
|
||||||
if (request == null) {
|
if (request == null)
|
||||||
|
{
|
||||||
_logger.LogError("An internal error has occurred");
|
_logger.LogError("An internal error has occurred");
|
||||||
return View("OidcError", new OpenIdConnectMessage {
|
return View("OidcError", new OpenIdConnectMessage
|
||||||
|
{
|
||||||
Error = OpenIdConnectConstants.Errors.ServerError,
|
Error = OpenIdConnectConstants.Errors.ServerError,
|
||||||
ErrorDescription = "An internal error has occurred"
|
ErrorDescription = "An internal error has occurred"
|
||||||
});
|
});
|
||||||
@ -327,7 +378,8 @@ ILogger _logger;
|
|||||||
|
|
||||||
[HttpPost("~/connect/logout")]
|
[HttpPost("~/connect/logout")]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task Logout(CancellationToken cancellationToken) {
|
public async Task Logout(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
// Instruct the cookies middleware to delete the local cookie created
|
// Instruct the cookies middleware to delete the local cookie created
|
||||||
// when the user agent is redirected from the external identity provider
|
// when the user agent is redirected from the external identity provider
|
||||||
// after a successful authentication flow (e.g Google or Facebook).
|
// after a successful authentication flow (e.g Google or Facebook).
|
||||||
@ -348,7 +400,7 @@ ILogger _logger;
|
|||||||
where application.ApplicationID == identifier
|
where application.ApplicationID == identifier
|
||||||
select application).SingleOrDefaultAsync(cancellationToken);
|
select application).SingleOrDefaultAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
private async Task<ApplicationUser> GetCurrentUserAsync()
|
private async Task<ApplicationUser> GetCurrentUserAsync()
|
||||||
{
|
{
|
||||||
return await _userManager.FindByIdAsync(HttpContext.User.GetUserId());
|
return await _userManager.FindByIdAsync(HttpContext.User.GetUserId());
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ namespace Yavsc.Helpers
|
|||||||
var content = await GetContent(output);
|
var content = await GetContent(output);
|
||||||
var markdown = content;
|
var markdown = content;
|
||||||
var basePath = Base?.StartsWith("~") ?? false ?
|
var basePath = Base?.StartsWith("~") ?? false ?
|
||||||
"/"+Startup.UserFilesDirName +
|
Constants.UserFilesDir +
|
||||||
Base.Substring(1) : Base;
|
Base.Substring(1) : Base;
|
||||||
var html = Markdown(markdown, basePath);
|
var html = Markdown(markdown, basePath);
|
||||||
output.Content.SetHtmlContent(html ?? "");
|
output.Content.SetHtmlContent(html ?? "");
|
||||||
|
@ -71,6 +71,12 @@ namespace Yavsc.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>tokens</returns>
|
/// <returns>tokens</returns>
|
||||||
public DbSet<OAuth2Tokens> Tokens { get; set; }
|
public DbSet<OAuth2Tokens> Tokens { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// References all declared external GCM devices
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public DbSet<GoogleCloudMobileDeclaration> GCMDevices { get; set; }
|
||||||
|
|
||||||
public Task ClearTokensAsync()
|
public Task ClearTokensAsync()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,28 @@ public class GoogleCloudMobileDeclaration {
|
|||||||
|
|
||||||
public string DeviceOwnerId { get; set; }
|
public string DeviceOwnerId { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
[ForeignKeyAttribute("DeviceOwnerId")]
|
[ForeignKeyAttribute("DeviceOwnerId")]
|
||||||
public virtual ApplicationUser DeviceOwner { get; set; }
|
public virtual ApplicationUser DeviceOwner { get; set; }
|
||||||
|
|
||||||
|
// override object.Equals
|
||||||
|
public override bool Equals (object obj)
|
||||||
|
{
|
||||||
|
if (obj == null || GetType() != obj.GetType())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var other = obj as GoogleCloudMobileDeclaration;
|
||||||
|
return RegistrationId == other.RegistrationId
|
||||||
|
&& Name == other.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// override object.GetHashCode
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (RegistrationId+Name).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,8 @@ namespace Yavsc.Services
|
|||||||
/// <returns>a MessageWithPayloadResponse,
|
/// <returns>a MessageWithPayloadResponse,
|
||||||
/// <c>bool somethingsent = (response.failure == 0 && response.success > 0)</c>
|
/// <c>bool somethingsent = (response.failure == 0 && response.success > 0)</c>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public async Task<MessageWithPayloadResponse> NotifyAsync(GoogleAuthSettings googleSettings, string registrationId, YaEvent ev)
|
public async Task<MessageWithPayloadResponse>
|
||||||
|
NotifyAsync(GoogleAuthSettings googleSettings, string registrationId, YaEvent ev)
|
||||||
{
|
{
|
||||||
MessageWithPayloadResponse response;
|
MessageWithPayloadResponse response;
|
||||||
try
|
try
|
||||||
|
@ -10,6 +10,7 @@ using System.Web.Optimization;
|
|||||||
using AspNet.Security.OpenIdConnect.Extensions;
|
using AspNet.Security.OpenIdConnect.Extensions;
|
||||||
using Microsoft.AspNet.Authentication;
|
using Microsoft.AspNet.Authentication;
|
||||||
using Microsoft.AspNet.Authentication.Cookies;
|
using Microsoft.AspNet.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNet.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNet.Authentication.OAuth;
|
using Microsoft.AspNet.Authentication.OAuth;
|
||||||
using Microsoft.AspNet.Authorization;
|
using Microsoft.AspNet.Authorization;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
@ -18,6 +19,7 @@ using Microsoft.AspNet.Diagnostics;
|
|||||||
using Microsoft.AspNet.FileProviders;
|
using Microsoft.AspNet.FileProviders;
|
||||||
using Microsoft.AspNet.Hosting;
|
using Microsoft.AspNet.Hosting;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Authentication;
|
||||||
using Microsoft.AspNet.Identity;
|
using Microsoft.AspNet.Identity;
|
||||||
using Microsoft.AspNet.Identity.EntityFramework;
|
using Microsoft.AspNet.Identity.EntityFramework;
|
||||||
using Microsoft.AspNet.Localization;
|
using Microsoft.AspNet.Localization;
|
||||||
@ -72,7 +74,7 @@ namespace Yavsc
|
|||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
public static string UserFilesDirName { get; private set; }
|
public static string UserFilesDirName { get; private set; }
|
||||||
private RsaSecurityKey key;
|
private RsaSecurityKey key;
|
||||||
|
|
||||||
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
|
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
|
||||||
@ -159,6 +161,16 @@ namespace Yavsc
|
|||||||
{
|
{
|
||||||
options.SignInScheme = "ServerCookie";
|
options.SignInScheme = "ServerCookie";
|
||||||
});
|
});
|
||||||
|
services.Configure<TokenAuthOptions>(
|
||||||
|
to =>
|
||||||
|
{
|
||||||
|
to.Audience = Configuration["Site:Audience"];
|
||||||
|
to.Issuer = Configuration["Site:Authority"];
|
||||||
|
to.SigningCredentials =
|
||||||
|
new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SiteSettings>), typeof(OptionsManager<SiteSettings>)));
|
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SiteSettings>), typeof(OptionsManager<SiteSettings>)));
|
||||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SmtpSettings>), typeof(OptionsManager<SmtpSettings>)));
|
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SmtpSettings>), typeof(OptionsManager<SmtpSettings>)));
|
||||||
@ -179,11 +191,7 @@ namespace Yavsc
|
|||||||
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication();
|
||||||
{
|
|
||||||
options.SignInScheme = "ServerCookie";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddEntityFramework()
|
services.AddEntityFramework()
|
||||||
.AddNpgsql()
|
.AddNpgsql()
|
||||||
@ -195,11 +203,15 @@ namespace Yavsc
|
|||||||
{
|
{
|
||||||
option.User.AllowedUserNameCharacters += " ";
|
option.User.AllowedUserNameCharacters += " ";
|
||||||
option.User.RequireUniqueEmail = true;
|
option.User.RequireUniqueEmail = true;
|
||||||
|
option.Cookies.ApplicationCookie.LoginPath = "/authenticate";
|
||||||
|
option.Cookies.ApplicationCookie.LogoutPath = "/signout";
|
||||||
|
option.Cookies.ApplicationCookie.AccessDeniedPath = "/forbidden"; // TODO /forbidden
|
||||||
|
// FIXME option.Cookies.ApplicationCookie.ReturnUrlParameter = "target";
|
||||||
}
|
}
|
||||||
).AddEntityFrameworkStores<ApplicationDbContext>()
|
).AddEntityFrameworkStores<ApplicationDbContext>()
|
||||||
.AddTokenProvider<EmailTokenProvider<ApplicationUser>>(Constants.EMailFactor)
|
.AddTokenProvider<EmailTokenProvider<ApplicationUser>>(Constants.EMailFactor)
|
||||||
.AddTokenProvider<UserTokenProvider>(Constants.DefaultFactor)
|
.AddTokenProvider<UserTokenProvider>(Constants.DefaultFactor)
|
||||||
;
|
;
|
||||||
// .AddTokenProvider<UserTokenProvider>(Constants.SMSFactor)
|
// .AddTokenProvider<UserTokenProvider>(Constants.SMSFactor)
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -229,14 +241,16 @@ namespace Yavsc
|
|||||||
{
|
{
|
||||||
policy.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Constants.AdminGroupName);
|
policy.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Constants.AdminGroupName);
|
||||||
});
|
});
|
||||||
|
|
||||||
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
|
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
|
||||||
options.AddPolicy("API", policy =>
|
options.AddPolicy("API", policy =>
|
||||||
{
|
{
|
||||||
|
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
|
||||||
policy.RequireClaim(OpenIdConnectConstants.Claims.Scope, "api-resource-controller");
|
policy.RequireClaim(OpenIdConnectConstants.Claims.Scope, "api-resource-controller");
|
||||||
});
|
});
|
||||||
// options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456"));
|
// options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456"));
|
||||||
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
|
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
|
||||||
|
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddSingleton<IAuthorizationHandler, HasBadgeHandler>();
|
services.AddSingleton<IAuthorizationHandler, HasBadgeHandler>();
|
||||||
@ -341,6 +355,7 @@ namespace Yavsc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var googleOptions = new GoogleOptions
|
var googleOptions = new GoogleOptions
|
||||||
{
|
{
|
||||||
ClientId = Configuration["Authentication:Google:ClientId"],
|
ClientId = Configuration["Authentication:Google:ClientId"],
|
||||||
@ -370,14 +385,54 @@ namespace Yavsc
|
|||||||
|
|
||||||
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
||||||
|
|
||||||
app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());
|
app.UseIISPlatformHandler(options =>
|
||||||
|
{
|
||||||
|
options.AuthenticationDescriptions.Clear();
|
||||||
|
options.AutomaticAuthentication = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseFileServer(new FileServerOptions()
|
||||||
|
{
|
||||||
|
FileProvider = new PhysicalFileProvider(
|
||||||
|
Path.Combine(
|
||||||
|
env.WebRootPath,
|
||||||
|
// TODO: add a ressource serveur id here,
|
||||||
|
// or remove the blog entry id usage, to use the userid instead
|
||||||
|
// and an user defined optional subdir.
|
||||||
|
siteSettings.Value.UserFiles.DirName
|
||||||
|
)),
|
||||||
|
RequestPath = new PathString("/" + siteSettings.Value.UserFiles.DirName),
|
||||||
|
EnableDirectoryBrowsing = false
|
||||||
|
});
|
||||||
app.UseStaticFiles().UseWebSockets();
|
app.UseStaticFiles().UseWebSockets();
|
||||||
|
|
||||||
app.UseRequestLocalization(localizationOptions.Value, (RequestCulture)new RequestCulture((string)"fr"));
|
|
||||||
|
|
||||||
app.UseIdentity();
|
app.UseIdentity();
|
||||||
|
|
||||||
|
app.UseOpenIdConnectServer(options =>
|
||||||
|
{
|
||||||
|
options.Provider = new AuthorizationProvider(loggerFactory);
|
||||||
|
|
||||||
|
// Register the certificate used to sign the JWT tokens.
|
||||||
|
/* options.SigningCredentials.AddCertificate(
|
||||||
|
assembly: typeof(Startup).GetTypeInfo().Assembly,
|
||||||
|
resource: "Mvc.Server.Certificate.pfx",
|
||||||
|
password: "Owin.Security.OpenIdConnect.Server"); */
|
||||||
|
|
||||||
|
// options.SigningCredentials.AddKey(key);
|
||||||
|
// Note: see AuthorizationController.cs for more
|
||||||
|
// information concerning ApplicationCanDisplayErrors.
|
||||||
|
options.ApplicationCanDisplayErrors = true;
|
||||||
|
options.AllowInsecureHttp = true;
|
||||||
|
options.AutomaticChallenge = true;
|
||||||
|
options.AuthorizationEndpointPath = new PathString("/connect/authorize");
|
||||||
|
options.TokenEndpointPath = new PathString("/connect/authorize/accept");
|
||||||
|
options.UseSlidingExpiration = true;
|
||||||
|
options.AllowInsecureHttp = true;
|
||||||
|
options.AuthenticationScheme = "oidc"; // was = OpenIdConnectDefaults.AuthenticationScheme;
|
||||||
|
options.LogoutEndpointPath = new PathString("/connect/logout");
|
||||||
|
|
||||||
|
/* options.ValidationEndpointPath = new PathString("/connect/introspect"); */
|
||||||
|
});
|
||||||
|
|
||||||
app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
|
app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
|
||||||
{
|
{
|
||||||
branch.UseJwtBearerAuthentication(options =>
|
branch.UseJwtBearerAuthentication(options =>
|
||||||
@ -401,7 +456,7 @@ namespace Yavsc
|
|||||||
options.AuthenticationScheme = "ServerCookie";
|
options.AuthenticationScheme = "ServerCookie";
|
||||||
options.CookieName = CookieAuthenticationDefaults.CookiePrefix + "ServerCookie";
|
options.CookieName = CookieAuthenticationDefaults.CookiePrefix + "ServerCookie";
|
||||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||||
options.LoginPath = new PathString("/signin");
|
options.LoginPath = new PathString("/authenticate");
|
||||||
options.LogoutPath = new PathString("/signout");
|
options.LogoutPath = new PathString("/signout");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -417,45 +472,10 @@ namespace Yavsc
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
var authProvider = new AuthorizationProvider(loggerFactory);
|
|
||||||
|
|
||||||
app.UseOpenIdConnectServer(options =>
|
|
||||||
{
|
|
||||||
options.Provider = authProvider;
|
|
||||||
|
|
||||||
// Register the certificate used to sign the JWT tokens.
|
|
||||||
/* options.SigningCredentials.AddCertificate(
|
|
||||||
assembly: typeof(Startup).GetTypeInfo().Assembly,
|
|
||||||
resource: "Mvc.Server.Certificate.pfx",
|
|
||||||
password: "Owin.Security.OpenIdConnect.Server"); */
|
|
||||||
|
|
||||||
// options.SigningCredentials.AddKey(key);
|
|
||||||
// Note: see AuthorizationController.cs for more
|
|
||||||
// information concerning ApplicationCanDisplayErrors.
|
|
||||||
options.ApplicationCanDisplayErrors = true;
|
|
||||||
options.AllowInsecureHttp = true;
|
|
||||||
options.AutomaticChallenge = true;
|
|
||||||
options.AuthorizationEndpointPath = new PathString("/connect/authorize");
|
|
||||||
options.TokenEndpointPath = new PathString("/connect/authorize/accept");
|
|
||||||
options.UseSlidingExpiration = true;
|
|
||||||
options.AllowInsecureHttp = true;
|
|
||||||
options.AuthenticationScheme = "oidc"; // was = OpenIdConnectDefaults.AuthenticationScheme;
|
|
||||||
options.LogoutEndpointPath = new PathString("/connect/logout");
|
|
||||||
|
|
||||||
/* options.ValidationEndpointPath = new PathString("/connect/introspect"); */
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseFileServer(new FileServerOptions()
|
|
||||||
{
|
|
||||||
FileProvider = new PhysicalFileProvider(
|
|
||||||
Path.Combine(
|
|
||||||
env.WebRootPath,
|
|
||||||
siteSettings.Value.UserFiles.DirName
|
|
||||||
)),
|
|
||||||
RequestPath = new PathString("/"+siteSettings.Value.UserFiles.DirName),
|
|
||||||
EnableDirectoryBrowsing = false
|
|
||||||
});
|
|
||||||
|
|
||||||
|
app.UseRequestLocalization(localizationOptions.Value, (RequestCulture)new RequestCulture((string)"fr"));
|
||||||
|
|
||||||
/* Generic OAuth (here GitHub): options.Notifications = new OAuthAuthenticationNotifications
|
/* Generic OAuth (here GitHub): options.Notifications = new OAuthAuthenticationNotifications
|
||||||
{
|
{
|
||||||
@ -501,12 +521,12 @@ namespace Yavsc
|
|||||||
}
|
}
|
||||||
}; */
|
}; */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
{
|
{
|
||||||
/* routes.MapRoute(
|
|
||||||
name: "wf",
|
|
||||||
template: "do/{action=Index}/{id?}",
|
|
||||||
defaults: new { controller = "WorkFlow" }); */
|
|
||||||
routes.MapRoute(
|
routes.MapRoute(
|
||||||
name: "default",
|
name: "default",
|
||||||
template: "{controller=Home}/{action=Index}/{id?}");
|
template: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
@ -13,9 +13,14 @@ textarea {
|
|||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-reac {
|
/* Set widths on image and video, since otherwise they use their native resolution */
|
||||||
|
|
||||||
|
img,
|
||||||
|
video {
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
/* .navbar-reac */
|
||||||
|
|
||||||
/* Carousel */
|
/* Carousel */
|
||||||
.carousel-caption p {
|
.carousel-caption p {
|
||||||
font-family: "jubilat";
|
font-family: "jubilat";
|
||||||
|
Reference in New Issue
Block a user