Browse Source

Fix github login.

pull/344/head
Sebastian Stehle 8 years ago
parent
commit
116d570f05
  1. 42
      src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorController.cs
  2. 16
      src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorViewModel.cs
  3. 6
      src/Squidex/Areas/IdentityServer/Startup.cs
  4. 1
      src/Squidex/Areas/IdentityServer/Views/Account/AccessDenied.cshtml
  5. 123
      src/Squidex/Areas/IdentityServer/Views/Account/Consent.cshtml
  6. 147
      src/Squidex/Areas/IdentityServer/Views/Account/Login.cshtml
  7. 1
      src/Squidex/Areas/IdentityServer/Views/Account/LogoutCompleted.cshtml
  8. 18
      src/Squidex/Areas/IdentityServer/Views/Error/Error.cshtml
  9. 359
      src/Squidex/Areas/IdentityServer/Views/Profile/Profile.cshtml
  10. 10
      src/Squidex/Areas/IdentityServer/Views/_Layout.cshtml
  11. 11
      src/Squidex/Config/Authentication/GithubHandler.cs

42
src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorController.cs

@ -5,16 +5,54 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Squidex.Infrastructure;
namespace Squidex.Areas.IdentityServer.Controllers.Error
{
public sealed class ErrorController : IdentityServerController
{
private readonly IIdentityServerInteractionService interaction;
public ErrorController(IIdentityServerInteractionService interaction)
{
this.interaction = interaction;
}
[Route("error/")]
public IActionResult Error()
public async Task<IActionResult> Error(string errorId = null)
{
return View();
var vm = new ErrorViewModel();
if (!string.IsNullOrWhiteSpace(errorId))
{
var message = await interaction.GetErrorContextAsync(errorId);
if (message != null)
{
vm.Error = message;
}
}
if (vm.Error == null)
{
var error = HttpContext.Features.Get<IExceptionHandlerFeature>()?.Error;
if (error is DomainException exception)
{
vm.Error = new ErrorMessage { ErrorDescription = exception.Message };
}
else if (error?.InnerException is DomainException exception2)
{
vm.Error = new ErrorMessage { ErrorDescription = exception2.Message };
}
}
return View("Error", vm);
}
}
}

16
src/Squidex/Areas/IdentityServer/Controllers/Error/ErrorViewModel.cs

@ -0,0 +1,16 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using IdentityServer4.Models;
namespace Squidex.Areas.IdentityServer.Controllers.Error
{
public class ErrorViewModel
{
public ErrorMessage Error { get; set; }
}
}

6
src/Squidex/Areas/IdentityServer/Startup.cs

@ -23,9 +23,7 @@ namespace Squidex.Areas.IdentityServer
app.Map(Constants.IdentityServerPrefix, identityApp =>
{
identityApp.UseMyIdentityServer();
if (environment.IsDevelopment())
if (!environment.IsDevelopment())
{
identityApp.UseDeveloperExceptionPage();
}
@ -34,6 +32,8 @@ namespace Squidex.Areas.IdentityServer
identityApp.UseExceptionHandler("/error");
}
identityApp.UseMyIdentityServer();
identityApp.UseStaticFiles();
identityApp.UseMvc();
});

1
src/Squidex/Areas/IdentityServer/Views/Account/AccessDenied.cshtml

@ -1,4 +1,5 @@
@{
ViewBag.Theme = "white";
ViewBag.Title = "Account locked";
}

123
src/Squidex/Areas/IdentityServer/Views/Account/Consent.cshtml

@ -1,7 +1,8 @@
@model Squidex.Areas.IdentityServer.Controllers.Account.ConsentVM
@{
ViewBag.Theme = "white";
ViewBag.Class = "profile-lg";
ViewBag.Title = "Consent";
}
@ -13,85 +14,81 @@
}
<form asp-controller="Account" asp-action="Consent" asp-route-returnurl="@Model.ReturnUrl" method="post">
<div class="profile profile-lg">
<img class="profile-logo" src="~/images/logo-small.png" />
<h2>We need your consent</h2>
<h2>We need your consent</h2>
<label for="consentToAutomatedEmails">
<div class="card profile-section-sm @ErrorClass("ConsentToAutomatedEmails")">
<div class="card-body">
<h4 class="card-title">Automated E-Mails (Optional)</h4>
<label for="consentToAutomatedEmails">
<div class="card profile-section-sm @ErrorClass("ConsentToAutomatedEmails")">
<div class="card-body">
<h4 class="card-title">Automated E-Mails (Optional)</h4>
<div class="card-text row">
<div class="col col-auto">
<input type="checkbox" id="consentToAutomatedEmails" name="consentToAutomatedEmails" value="True" />
</div>
<div class="col">
I understand and agree that Squidex sends Emails to inform me about new features, breaking changes and down times.
</div>
<div class="card-text row">
<div class="col col-auto">
<input type="checkbox" id="consentToAutomatedEmails" name="consentToAutomatedEmails" value="True" />
</div>
<div class="col">
I understand and agree that Squidex sends Emails to inform me about new features, breaking changes and down times.
</div>
</div>
</div>
</label>
</div>
</label>
<label for="consentToCookies">
<div class="card profile-section-sm @ErrorClass("ConsentToCookies")">
<div class="card-body">
<h4 class="card-title">Cookies & Analytics</h4>
<label for="consentToCookies">
<div class="card profile-section-sm @ErrorClass("ConsentToCookies")">
<div class="card-body">
<h4 class="card-title">Cookies & Analytics</h4>
<div class="card-text row">
<div class="col col-auto">
<input type="checkbox" id="consentToCookies" name="consentToCookies" value="True" />
</div>
<div class="col">
<p>
I understand and agree that Squidex uses cookies to ensure you get the best experience on our platform and to store your login status.
</p>
<p>
I understand and agree that Squidex has integrated Google Analytics (with the anonymizer function). Google Analytics is a web analytics service to gather and analyse data about the behavior of users.
</p>
<p>
I accept the <a href="@Model.PrivacyUrl" target="_blank" rel="noopener">privacy policies</a>.
</p>
</div>
<div class="card-text row">
<div class="col col-auto">
<input type="checkbox" id="consentToCookies" name="consentToCookies" value="True" />
</div>
<div class="col">
<p>
I understand and agree that Squidex uses cookies to ensure you get the best experience on our platform and to store your login status.
</p>
<p>
I understand and agree that Squidex has integrated Google Analytics (with the anonymizer function). Google Analytics is a web analytics service to gather and analyse data about the behavior of users.
</p>
<p>
I accept the <a href="@Model.PrivacyUrl" target="_blank" rel="noopener">privacy policies</a>.
</p>
</div>
</div>
</div>
</label>
</div>
</label>
<label for="consentToPersonalInformation">
<div class="card profile-section-sm @ErrorClass("ConsentToPersonalInformation")">
<div class="card-body">
<h4 class="card-title">Personal Information</h4>
<label for="consentToPersonalInformation">
<div class="card profile-section-sm @ErrorClass("ConsentToPersonalInformation")">
<div class="card-body">
<h4 class="card-title">Personal Information</h4>
<div class="card-text row">
<div class="col col-auto">
<input type="checkbox" id="consentToPersonalInformation" name="consentToPersonalInformation" value="True" />
</div>
<div class="col">
I understand and agree that Squidex collects the following private information that are retrieved from external authentication providers such as Google, Microsoft or Github.
<div class="card-text row">
<div class="col col-auto">
<input type="checkbox" id="consentToPersonalInformation" name="consentToPersonalInformation" value="True" />
</div>
<div class="col">
I understand and agree that Squidex collects the following private information that are retrieved from external authentication providers such as Google, Microsoft or Github.
<ul class="personal-information">
<li>
Basic personal information (first name, last name and picture) are provided to all other users so that they can add you to their working space.
</li>
<li>
At anytime you have the option to change these information to anonymize your account.
</li>
<li>
Your user account has an unique identifier and for all your changes we track, that you made these changes and provide this information to other users.
</li>
</ul>
<ul class="personal-information">
<li>
Basic personal information (first name, last name and picture) are provided to all other users so that they can add you to their working space.
</li>
<li>
At anytime you have the option to change these information to anonymize your account.
</li>
<li>
Your user account has an unique identifier and for all your changes we track, that you made these changes and provide this information to other users.
</li>
</ul>
</div>
</div>
</div>
</div>
</label>
<div class="profile-section-sm text-right">
<button type="submit" class="btn btn-success">I agree!</button>
</div>
</label>
<div class="profile-section-sm text-right">
<button type="submit" class="btn btn-success">I agree!</button>
</div>
</form>

147
src/Squidex/Areas/IdentityServer/Views/Account/Login.cshtml

@ -3,96 +3,91 @@
@{
var type = Model.IsLogin ? "Login" : "Signup";
ViewBag.Theme = "white";
ViewBag.Title = type;
}
<div class="profile">
<img class="profile-logo" src="~/images/logo-small.png" />
<div class="container">
<div class="row text-center">
<div class="btn-group profile-headline">
@if (Model.IsLogin)
{
<a class="btn btn-toggle btn-primary" asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl">Login</a>
}
else
{
<a class="btn btn-toggle" asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl">Login</a>
}
@if (!Model.IsLogin)
{
<a class="btn btn-toggle btn-primary" asp-controller="Account" asp-action="Signup" asp-route-returnurl="@Model.ReturnUrl">Signup</a>
}
else
{
<a class="btn btn-toggle" asp-controller="Account" asp-action="Signup" asp-route-returnurl="@Model.ReturnUrl">Signup</a>
}
</div>
<div class="container">
<div class="row text-center">
<div class="btn-group profile-headline">
@if (Model.IsLogin)
{
<a class="btn btn-toggle btn-primary" asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl">Login</a>
}
else
{
<a class="btn btn-toggle" asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl">Login</a>
}
@if (!Model.IsLogin)
{
<a class="btn btn-toggle btn-primary" asp-controller="Account" asp-action="Signup" asp-route-returnurl="@Model.ReturnUrl">Signup</a>
}
else
{
<a class="btn btn-toggle" asp-controller="Account" asp-action="Signup" asp-route-returnurl="@Model.ReturnUrl">Signup</a>
}
</div>
</div>
</div>
<form asp-controller="Account" asp-action="External" asp-route-returnurl="@Model.ReturnUrl" method="post">
@foreach (var provider in Model.ExternalProviders)
{
var schema = provider.AuthenticationScheme.ToLowerInvariant();
<div class="form-group">
<button class="btn external-button btn-block btn btn-@schema" type="submit" name="provider" value="@provider.AuthenticationScheme">
<i class="icon-@schema external-icon"></i> @type with <strong>@provider.AuthenticationScheme</strong>
</button>
</div>
}
</form>
@if (Model.HasPasswordAndExternal)
<form asp-controller="Account" asp-action="External" asp-route-returnurl="@Model.ReturnUrl" method="post">
@foreach (var provider in Model.ExternalProviders)
{
<div class="profile-separator">
<div class="profile-separator-text">OR</div>
var schema = provider.AuthenticationScheme.ToLowerInvariant();
<div class="form-group">
<button class="btn external-button btn-block btn btn-@schema" type="submit" name="provider" value="@provider.AuthenticationScheme">
<i class="icon-@schema external-icon"></i> @type with <strong>@provider.AuthenticationScheme</strong>
</button>
</div>
}
</form>
@if (Model.HasPasswordAuth)
{
if (Model.IsLogin)
{
if (Model.IsFailed)
{
<div class="form-alert form-alert-error">Email or password not correct.</div>
}
@if (Model.HasPasswordAndExternal)
{
<div class="profile-separator">
<div class="profile-separator-text">OR</div>
</div>
}
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl" method="post">
<div class="form-group">
<input type="email" class="form-control" name="email" id="email" placeholder="Enter Email" />
</div>
@if (Model.HasPasswordAuth)
{
if (Model.IsLogin)
{
if (Model.IsFailed)
{
<div class="form-alert form-alert-error">Email or password not correct.</div>
}
<div class="form-group">
<input type="password" class="form-control" name="password" id="password" placeholder="Enter Password" />
</div>
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl" method="post">
<div class="form-group">
<input type="email" class="form-control" name="email" id="email" placeholder="Enter Email" />
</div>
<button type="submit" class="btn btn-block btn-primary">@type</button>
</form>
}
else
{
<div class="profile-password-signup text-center">Ask your administrator to create an account.</div>
}
}
<div class="form-group">
<input type="password" class="form-control" name="password" id="password" placeholder="Enter Password" />
</div>
@if (Model.IsLogin)
{
<p class="profile-footer">
No account yet? <a asp-controller="Account" asp-action="Signup" asp-route-returnurl="@Model.ReturnUrl">Click here to signup</a>
</p>
}
else
{
<p class="profile-footer">
Already registered? <a asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl">Click here to login</a>
</p>
}
</div>
<button type="submit" class="btn btn-block btn-primary">@type</button>
</form>
}
else
{
<div class="profile-password-signup text-center">Ask your administrator to create an account.</div>
}
}
@if (Model.IsLogin)
{
<p class="profile-footer">
No account yet? <a asp-controller="Account" asp-action="Signup" asp-route-returnurl="@Model.ReturnUrl">Click here to signup</a>
</p>
}
else
{
<p class="profile-footer">
Already registered? <a asp-controller="Account" asp-action="Login" asp-route-returnurl="@Model.ReturnUrl">Click here to login</a>
</p>
}
@if (!Model.HasPasswordAuth && Model.ExternalProviders.Count == 1)
{

1
src/Squidex/Areas/IdentityServer/Views/Account/LogoutCompleted.cshtml

@ -1,4 +1,5 @@
@{
ViewBag.Theme = "white";
ViewBag.Title = "Logout";
}

18
src/Squidex/Areas/IdentityServer/Views/Error/Error.cshtml

@ -1,9 +1,19 @@
@{
@model Squidex.Areas.IdentityServer.Controllers.Error.ErrorViewModel
@{
ViewBag.Theme = "white";
ViewBag.Title = "Operation failed";
}
<h1 class="splash-h1">Operation failed</h1>
<p class="splash-text">
We are really sorry that something went wrong.
</p>
@if (Model.Error?.ErrorDescription != null)
{
@Model.Error.ErrorDescription
}
else
{
<span>We are really sorry that something went wrong.</span>
}
</p>

359
src/Squidex/Areas/IdentityServer/Views/Profile/Profile.cshtml

@ -1,223 +1,218 @@
@model Squidex.Areas.IdentityServer.Controllers.Profile.ProfileVM
@{
ViewBag.Theme = "white";
ViewBag.Title = "Profile";
}
<div class="profile profile-lg">
<img class="profile-logo" src="~/images/logo-small.png" />
<h1>Edit Profile</h1>
<h1>Edit Profile</h1>
<h2>Personal Information</h2>
<h2>Personal Information</h2>
@if (!string.IsNullOrWhiteSpace(Model.SuccessMessage))
{
<div class="form-alert form-alert-success" id="success">
@Model.SuccessMessage
</div>
}
@if (!string.IsNullOrWhiteSpace(Model.SuccessMessage))
{
<div class="form-alert form-alert-success" id="success">
@Model.SuccessMessage
</div>
}
@if (!string.IsNullOrWhiteSpace(Model.ErrorMessage))
{
<div class="form-alert form-alert-error">
@Model.ErrorMessage
</div>
}
@if (!string.IsNullOrWhiteSpace(Model.ErrorMessage))
{
<div class="form-alert form-alert-error">
@Model.ErrorMessage
</div>
}
<div class="row profile-section">
<div class="col profile-picture-col">
<img class="profile-picture" src="@Url.Content($"~/../api/users/{Model.Id}/picture/")" />
</div>
<div class="col">
<form id="pictureForm" class="profile-picture-form" asp-controller="Profile" asp-action="UploadPicture" method="post" enctype="multipart/form-data">
<span class="btn btn-secondary" id="pictureButton">
<span>Upload Picture</span>
<input class="profile-picture-input" name="file" type="file" id="pictureInput" />
</span>
</form>
</div>
<div class="row profile-section">
<div class="col profile-picture-col">
<img class="profile-picture" src="@Url.Content($"~/../api/users/{Model.Id}/picture/")" />
</div>
<div class="col">
<form id="pictureForm" class="profile-picture-form" asp-controller="Profile" asp-action="UploadPicture" method="post" enctype="multipart/form-data">
<span class="btn btn-secondary" id="pictureButton">
<span>Upload Picture</span>
<input class="profile-picture-input" name="file" type="file" id="pictureInput" />
</span>
</form>
</div>
</div>
<form class="profile-form profile-section" asp-controller="Profile" asp-action="UpdateProfile" method="post">
<div class="form-group">
<label for="email">Email</label>
<form class="profile-form profile-section" asp-controller="Profile" asp-action="UpdateProfile" method="post">
<div class="form-group">
<label for="email">Email</label>
@if (ViewContext.ViewData.ModelState["Email"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span asp-validation-for="Email" class="errors"></span>
</div>
}
@if (ViewContext.ViewData.ModelState["Email"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span asp-validation-for="Email" class="errors"></span>
</div>
}
<input type="email" ap class="form-control" asp-for="Email" id="email" />
</div>
<input type="email" ap class="form-control" asp-for="Email" id="email" />
</div>
<div class="form-group">
<label for="displayName">Display Name</label>
<div class="form-group">
<label for="displayName">Display Name</label>
@if (ViewContext.ViewData.ModelState["DisplayName"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span asp-validation-for="DisplayName" class="errors"></span>
</div>
}
@if (ViewContext.ViewData.ModelState["DisplayName"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span asp-validation-for="DisplayName" class="errors"></span>
</div>
}
<input type="text" class="form-control" asp-for="DisplayName" id="displayName"/>
</div>
<input type="text" class="form-control" asp-for="DisplayName" id="displayName"/>
</div>
<div class="form-group">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="IsHidden" id="hidden" />
<div class="form-group">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="IsHidden" id="hidden" />
<label class="form-check-label" for="hidden">Do not show my profile to other users</label>
</div>
<label class="form-check-label" for="hidden">Do not show my profile to other users</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
@if (Model.ExternalProviders.Any())
{
<div class="profile-section">
<h2>Logins</h2>
<table class="table table-fixed table-lesspadding">
<colgroup>
<col style="width: 100px;"/>
<col style="width: 100%;"/>
<col style="width: 100px;"/>
</colgroup>
@foreach (var login in Model.ExternalLogins)
{
<tr>
<td>
<span>@login.LoginProvider</span>
</td>
<td>
<span class="truncate">@login.ProviderDisplayName</span>
</td>
<td class="text-right">
@if (Model.ExternalLogins.Count > 1 || Model.HasPassword)
{
<form asp-controller="Profile" asp-action="RemoveLogin" method="post">
<input type="hidden" value="@login.LoginProvider" name="LoginProvider"/>
<input type="hidden" value="@login.ProviderKey" name="ProviderKey"/>
<button type="submit" class="btn btn-text-danger btn-sm">
Remove
</button>
</form>
}
</td>
</tr>
}
</table>
<form asp-controller="Profile" asp-action="AddLogin" method="post">
@foreach (var provider in Model.ExternalProviders.Where(x => Model.ExternalLogins.All(y => x.AuthenticationScheme != y.LoginProvider)))
{
var schema = provider.AuthenticationScheme.ToLowerInvariant();
<button class="btn external-button-small btn-@schema" type="submit" name="provider" value="@provider.AuthenticationScheme">
<i class="icon-@schema external-icon"></i>
</button>
}
</form>
</div>
}
<button type="submit" class="btn btn-primary">Save</button>
</form>
@if (Model.HasPasswordAuth)
{
<div class="profile-section">
<h2>Password</h2>
@if (Model.HasPassword)
@if (Model.ExternalProviders.Any())
{
<div class="profile-section">
<h2>Logins</h2>
<table class="table table-fixed table-lesspadding">
<colgroup>
<col style="width: 100px;"/>
<col style="width: 100%;"/>
<col style="width: 100px;"/>
</colgroup>
@foreach (var login in Model.ExternalLogins)
{
<form class="profile-form" asp-controller="Profile" asp-action="ChangePassword" method="post">
<div class="form-group">
<label for="oldPassword">Old Password</label>
@if (ViewContext.ViewData.ModelState["OldPassword"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
<tr>
<td>
<span>@login.LoginProvider</span>
</td>
<td>
<span class="truncate">@login.ProviderDisplayName</span>
</td>
<td class="text-right">
@if (Model.ExternalLogins.Count > 1 || Model.HasPassword)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("OldPassword")</span>
</div>
<form asp-controller="Profile" asp-action="RemoveLogin" method="post">
<input type="hidden" value="@login.LoginProvider" name="LoginProvider"/>
<input type="hidden" value="@login.ProviderKey" name="ProviderKey"/>
<button type="submit" class="btn btn-text-danger btn-sm">
Remove
</button>
</form>
}
</td>
</tr>
}
</table>
<input type="password" class="form-control" name="oldPassword" id="oldPassword" />
</div>
<div class="form-group">
<label for="password">Password</label>
<form asp-controller="Profile" asp-action="AddLogin" method="post">
@foreach (var provider in Model.ExternalProviders.Where(x => Model.ExternalLogins.All(y => x.AuthenticationScheme != y.LoginProvider)))
{
var schema = provider.AuthenticationScheme.ToLowerInvariant();
@if (ViewContext.ViewData.ModelState["Password"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("Password")</span>
</div>
}
<button class="btn external-button-small btn-@schema" type="submit" name="provider" value="@provider.AuthenticationScheme">
<i class="icon-@schema external-icon"></i>
</button>
}
</form>
</div>
}
@if (Model.HasPasswordAuth)
{
<div class="profile-section">
<h2>Password</h2>
@if (Model.HasPassword)
{
<form class="profile-form" asp-controller="Profile" asp-action="ChangePassword" method="post">
<div class="form-group">
<label for="oldPassword">Old Password</label>
@if (ViewContext.ViewData.ModelState["OldPassword"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("OldPassword")</span>
</div>
}
<input type="password" class="form-control" name="oldPassword" id="oldPassword" />
</div>
<input type="password" class="form-control" name="password" id="password" />
</div>
<div class="form-group">
<label for="password">Password</label>
<div class="form-group">
<label for="passwordConfirm">Confirm</label>
@if (ViewContext.ViewData.ModelState["Password"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("Password")</span>
</div>
}
@if (ViewContext.ViewData.ModelState["PasswordConfirm"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("PasswordConfirm")</span>
</div>
}
<input type="password" class="form-control" name="password" id="password" />
</div>
<input type="password" class="form-control" name="passwordConfirm" id="passwordConfirm" />
</div>
<div class="form-group">
<label for="passwordConfirm">Confirm</label>
<div class="form-group">
<button type="submit" class="btn btn-primary">Change Password</button>
</div>
</form>
}
else
{
<form class="profile-form" asp-controller="Profile" asp-action="SetPassword" method="post">
<div class="form-group">
<label for="password">Password</label>
@if (ViewContext.ViewData.ModelState["PasswordConfirm"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("PasswordConfirm")</span>
</div>
}
@if (ViewContext.ViewData.ModelState["Password"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("Password")</span>
</div>
}
<input type="password" class="form-control" name="passwordConfirm" id="passwordConfirm" />
</div>
<input type="password" class="form-control" name="password" id="password" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Change Password</button>
</div>
</form>
}
else
{
<form class="profile-form" asp-controller="Profile" asp-action="SetPassword" method="post">
<div class="form-group">
<label for="password">Password</label>
@if (ViewContext.ViewData.ModelState["Password"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("Password")</span>
</div>
}
<input type="password" class="form-control" name="password" id="password" />
</div>
<div class="form-group">
<label for="passwordConfirm">Confirm</label>
<div class="form-group">
<label for="passwordConfirm">Confirm</label>
@if (ViewContext.ViewData.ModelState["PasswordConfirm"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("PasswordConfirm")</span>
</div>
}
@if (ViewContext.ViewData.ModelState["PasswordConfirm"]?.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
<div class="errors-container">
<span class="errors">@Html.ValidationMessage("PasswordConfirm")</span>
</div>
}
<input type="password" class="form-control" name="passwordConfirm" id="passwordConfirm" />
</div>
<input type="password" class="form-control" name="passwordConfirm" id="passwordConfirm" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Set Password</button>
</div>
</form>
}
</div>
}
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Set Password</button>
</div>
</form>
}
</div>
}
<script>
var pictureButton = document.getElementById('pictureButton');

10
src/Squidex/Areas/IdentityServer/Views/_Layout.cshtml

@ -17,9 +17,13 @@
@RenderSection("header")
}
</head>
<body class="@ViewBag.Theme">
@RenderBody()
<body class="white">
<div class="profile @ViewBag.Class">
<img class="profile-logo" src="~/images/logo-small.png" />
@RenderBody()
</div>
<environment names="Development">
<script type="text/javascript" src="http://localhost:3000/shims.js"></script>
<script type="text/javascript" src="http://localhost:3000/app.js"></script>

11
src/Squidex/Config/Authentication/GithubHandler.cs

@ -6,14 +6,20 @@
// ==========================================================================
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.Extensions.Options;
using Squidex.Infrastructure;
using Squidex.Shared.Identity;
namespace Squidex.Config.Authentication
{
public sealed class GithubHandler : OAuthEvents
{
private const string NoEmail = "Your email address is set to private in Github. Please set it to public to use Github login.";
public override Task CreatingTicket(OAuthCreatingTicketContext context)
{
var nameClaim = context.Identity.FindFirst(ClaimTypes.Name)?.Value;
@ -23,6 +29,11 @@ namespace Squidex.Config.Authentication
context.Identity.SetDisplayName(nameClaim);
}
if (string.IsNullOrWhiteSpace(context.Identity.FindFirst(ClaimTypes.Email)?.Value))
{
throw new DomainException(NoEmail);
}
return base.CreatingTicket(context);
}
}

Loading…
Cancel
Save