Initial commit
This commit is contained in:
69
Views/Accounts/Index.cshtml
Normal file
69
Views/Accounts/Index.cshtml
Normal file
@@ -0,0 +1,69 @@
|
||||
@using SimpleIdp.Resources
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.AccountsIndexViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = AccountsResource.select_session;
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
<h1>@AccountsResource.active_sessions</h1>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(ViewBag.IsUserAccountSwitched))
|
||||
{
|
||||
<div class="alert alert-success">@AccountsResource.useraccount_switched</div>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(ViewBag.IsSessionRejected))
|
||||
{
|
||||
<div class="alert alert-success">@AccountsResource.useraccount_rejected</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
@{
|
||||
int i = 0;
|
||||
foreach (var account in Model.Accounts)
|
||||
{
|
||||
i++;
|
||||
string rejectFormId = "reject-" + i;
|
||||
<div class="col-md-4">
|
||||
@using (Html.BeginForm("Index", "Accounts", FormMethod.Post))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="card">
|
||||
<input type="hidden" name="AccountName" value="@account.Name" />
|
||||
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||
<input type="hidden" name="Action" value="Choose" />
|
||||
<div class="card-header">@account.Name</div>
|
||||
<div class="card-body">
|
||||
@if (account.IssuedUtc != null)
|
||||
{
|
||||
<p>
|
||||
@string.Format(AccountsResource.authentication_time, account.IssuedUtc.Value.ToString("s"))
|
||||
</p>
|
||||
}
|
||||
@if (account.ExpiresUct != null)
|
||||
{
|
||||
<p>
|
||||
@string.Format(AccountsResource.expiration_time, account.ExpiresUct.Value.ToString("s"))
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-between">
|
||||
<input type="submit" class="btn btn-primary" value="@AccountsResource.choose_session" />
|
||||
<input type="submit" class="btn btn-danger" form="@rejectFormId" value="@AccountsResource.reject" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@using (Html.BeginForm("Index", "Accounts", FormMethod.Post, new { id = rejectFormId }))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="AccountName" value="@account.Name" />
|
||||
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||
<input type="hidden" name="Action" value="Reject" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
}
|
||||
</div>
|
||||
74
Views/BackChannelConsents/Index.cshtml
Normal file
74
Views/BackChannelConsents/Index.cshtml
Normal file
@@ -0,0 +1,74 @@
|
||||
@using SimpleIdp.Resources
|
||||
@using SimpleIdServer.IdServer.UI.ViewModels
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.BCConsentsIndexViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = LayoutResource.consents;
|
||||
Layout = "~/Views/Shared/_CommonLayout.cshtml";
|
||||
}
|
||||
|
||||
<div class="consentContainer">
|
||||
<div class="card consent">
|
||||
<div class="card-body">
|
||||
@if(Model.IsConfirmed)
|
||||
{
|
||||
<div class="alert alert-success">
|
||||
@(Model.ConfirmationStatus == ConfirmationStatus.CONFIRMED ? BCConsentsResource.consent_confirmed : BCConsentsResource.consent_rejected)
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<form method="post" action="@Url.Action("Reject", "BackChannelConsents")" id="rejectForm">
|
||||
@Html.AntiForgeryToken()
|
||||
<input name="ReturnUrl" type="hidden" value="@Model.ReturnUrl" />
|
||||
<input name="IsRejected" type="hidden" value="true" />
|
||||
</form>
|
||||
@using (Html.BeginForm("Index", "BackChannelConsents", FormMethod.Post))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
@if (!ViewData.ModelState.IsValid)
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var modelState in ViewData.ModelState.Values)
|
||||
{
|
||||
foreach (var error in modelState.Errors)
|
||||
{
|
||||
<li class="list-group-item list-group-item-danger">@BCConsentsResource.ResourceManager.GetString(error.ErrorMessage)</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
|
||||
<input type="hidden" value="@Model.ReturnUrl" name="ReturnUrl" />
|
||||
<input name="IsRejected" type="hidden" value="false" />
|
||||
|
||||
<h5>@string.Format(BCConsentsResource.consent_client_access, Model.ClientName)</h5>
|
||||
<ul class="list-group">
|
||||
@if (!string.IsNullOrWhiteSpace(Model.BindingMessage))
|
||||
{
|
||||
<li class="list-group-item"><b>@BCConsentsResource.message</b> : @Model.BindingMessage</li>
|
||||
}
|
||||
|
||||
@if(Model.Scopes == null || !Model.Scopes.Any())
|
||||
{
|
||||
<li class="list-group-item"><b>@BCConsentsResource.scopes</b> : @string.Join(",", Model.Scopes)</li>
|
||||
}
|
||||
|
||||
@if(Model.AuthorizationDetails != null && Model.AuthorizationDetails.Any())
|
||||
{
|
||||
foreach(var authDetail in Model.AuthorizationDetails)
|
||||
{
|
||||
<li class="list-group-item"><b>@authDetail.Type</b> : @string.Join(",", authDetail.Actions)</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn btn-success card-link">@BCConsentsResource.confirm</button>
|
||||
<button type="submit" form="rejectForm" class="btn btn-danger">@BCConsentsResource.reject</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
41
Views/CheckSession/EndSession.cshtml
Normal file
41
Views/CheckSession/EndSession.cshtml
Normal file
@@ -0,0 +1,41 @@
|
||||
@using Microsoft.Extensions.Options;
|
||||
@using SimpleIdServer.IdServer.Options;
|
||||
@using SimpleIdp.Resources
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.RevokeSessionViewModel
|
||||
@inject IOptions<IdServerHostOptions> options
|
||||
|
||||
@{
|
||||
ViewBag.Title = CheckSessionResource.revoke_session_title;
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
@foreach (var frontChannelLogout in Model.FrontChannelLogouts)
|
||||
{
|
||||
<iframe src="@frontChannelLogout" style="display: none"></iframe>
|
||||
}
|
||||
|
||||
@if(Model.RedirectToRevokeSessionUI)
|
||||
{
|
||||
<a href="@Model.RevokeSessionCallbackUrl" class="btn btn-danger">@CheckSessionResource.revoke_session_title</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-info">
|
||||
<p>@string.Format(CheckSessionResource.session_being_revoked, (options.Value.EndSessionRedirectionTimeInMS / 1000))</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@section Scripts {
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var isRedirected = '@Model.RedirectToRevokeSessionUI.ToString().ToLowerInvariant()' == 'false';
|
||||
var callback = '@Html.Raw(Model.RevokeSessionCallbackUrl)';
|
||||
var timeMS = parseInt('@options.Value.EndSessionRedirectionTimeInMS');
|
||||
if(isRedirected) {
|
||||
setTimeout(() => {
|
||||
window.location.replace(callback);
|
||||
}, timeMS);
|
||||
}
|
||||
})
|
||||
</script>
|
||||
}
|
||||
92
Views/Consents/Index.cshtml
Normal file
92
Views/Consents/Index.cshtml
Normal file
@@ -0,0 +1,92 @@
|
||||
@using SimpleIdServer.IdServer.DTOs
|
||||
@using SimpleIdServer.IdServer.Domains;
|
||||
@using SimpleIdp.Resources
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.ConsentsIndexViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = LayoutResource.consents;
|
||||
Layout = "~/Views/Shared/_CommonLayout.cshtml";
|
||||
}
|
||||
|
||||
<div class="consentContainer">
|
||||
<div class="card consent">
|
||||
<div class="card-body">
|
||||
<!-- Rejection form -->
|
||||
<form method="post" action="@Url.Action("Reject", "Consents")" id="rejectForm">
|
||||
@Html.AntiForgeryToken()
|
||||
<input name="ReturnUrl" type="hidden" value="@Model.ReturnUrl" />
|
||||
</form>
|
||||
<div class="consentinfo">
|
||||
<div class="img">
|
||||
@Html.UserPicture(User)
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="img">
|
||||
@Html.ClientPicture(Model.PictureUri)
|
||||
</div>
|
||||
</div>
|
||||
<!-- Confirmation form -->
|
||||
@using (Html.BeginForm("Index", "Consents", FormMethod.Post))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
@if (!ViewData.ModelState.IsValid)
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var modelState in ViewData.ModelState.Values)
|
||||
{
|
||||
foreach (var error in modelState.Errors)
|
||||
{
|
||||
<li class="list-group-item list-group-item-danger">@ConsentsResource.ResourceManager.GetString(error.ErrorMessage)</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
|
||||
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||
<h5>@string.Format(ConsentsResource.consent_client_access, Model.ClientName)</h5>
|
||||
<ul class="list-group">
|
||||
@if(Model.ScopeNames != null && Model.ScopeNames.Any())
|
||||
{
|
||||
<li class="list-group-item"><b>@ConsentsResource.scopes</b> : @string.Join(",", Model.ScopeNames)</li>
|
||||
}
|
||||
|
||||
@if(Model.ClaimNames != null && Model.ClaimNames.Any())
|
||||
{
|
||||
<li class="list-group-item"><b>@ConsentsResource.claims</b> : @string.Join(",", Model.ClaimNames)</li>
|
||||
}
|
||||
|
||||
@if (Model.AuthorizationDetails != null && Model.AuthorizationDetails.Any())
|
||||
{
|
||||
foreach (var authDetail in Model.AuthorizationDetails)
|
||||
{
|
||||
if (authDetail.Type == AuthorizationDetailsNames.OpenIdCredential)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="list-group-item">
|
||||
<b>@authDetail.Type</b> : @string.Join(",", authDetail.Actions)
|
||||
@if (authDetail.Locations != null && authDetail.Locations.Any())
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var location in authDetail.Locations)
|
||||
{
|
||||
<li class="list-group-item">@location</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn btn-success card-link">@ConsentsResource.confirm</button>
|
||||
<button type="submit" form="rejectForm" class="btn btn-danger">@ConsentsResource.reject</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
66
Views/Device/Index.cshtml
Normal file
66
Views/Device/Index.cshtml
Normal file
@@ -0,0 +1,66 @@
|
||||
@using SimpleIdServer.IdServer.Domains;
|
||||
@using SimpleIdp.Resources
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.DeviceCodeViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = LayoutResource.deviceauth;
|
||||
Layout = "~/Views/Shared/_CommonLayout.cshtml";
|
||||
}
|
||||
|
||||
<div class="consentContainer">
|
||||
<div class="card consent">
|
||||
<div class="card-body">
|
||||
@if(Model.IsConfirmed)
|
||||
{
|
||||
<div class="alert alert-success">
|
||||
@DeviceCodeResource.confirmed
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="consentinfo">
|
||||
<div class="img">
|
||||
@Html.UserPicture(User)
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="img">
|
||||
@Html.ClientPicture(Model.PictureUri)
|
||||
</div>
|
||||
</div>
|
||||
<!-- Confirmation form -->
|
||||
@using (Html.BeginForm("Index", "Device", FormMethod.Post))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
@if (!ViewData.ModelState.IsValid)
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var modelState in ViewData.ModelState.Values)
|
||||
{
|
||||
foreach (var error in modelState.Errors)
|
||||
{
|
||||
<li class="list-group-item list-group-item-danger">@DeviceCodeResource.ResourceManager.GetString(error.ErrorMessage)</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
|
||||
<h5>@string.Format(DeviceCodeResource.consent_client_access, Model.ClientName)</h5>
|
||||
<ul class="list-group">
|
||||
@if (Model.Scopes != null && Model.Scopes.Any())
|
||||
{
|
||||
<li class="list-group-item"><b>@DeviceCodeResource.scopes</b> : @string.Join(",", Model.Scopes)</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div class="input-group mb-3 mt-3">
|
||||
<input type="text" value="@Model.UserCode" name="UserCode" class="form-control" placeholder="@DeviceCodeResource.usercode">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn btn-success card-link">@DeviceCodeResource.confirm</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
11
Views/Errors/Index.cshtml
Normal file
11
Views/Errors/Index.cshtml
Normal file
@@ -0,0 +1,11 @@
|
||||
@using SimpleIdp.Resources
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.ErrorViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = "Error";
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
<div class="alert alert-danger" role="alert">
|
||||
@Model.Message
|
||||
</div>
|
||||
10
Views/Errors/Unexpected.cshtml
Normal file
10
Views/Errors/Unexpected.cshtml
Normal file
@@ -0,0 +1,10 @@
|
||||
@using SimpleIdp.Resources
|
||||
|
||||
@{
|
||||
ViewBag.Title = "Error";
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
<div class="alert alert-danger" role="alert">
|
||||
@LayoutResource.UnexpectedError
|
||||
</div>
|
||||
17
Views/Home/Disconnect.cshtml
Normal file
17
Views/Home/Disconnect.cshtml
Normal file
@@ -0,0 +1,17 @@
|
||||
@using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
@using SimpleIdp.Resources
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.DisconnectViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = LayoutResource.Disconnected;
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
<h6>@LayoutResource.YouAreDisconnected</h6>
|
||||
|
||||
@foreach (var frontChannelLogout in Model.FrontChannelLogoutUrls)
|
||||
{
|
||||
<iframe src="@frontChannelLogout" style="display: none"></iframe>
|
||||
}
|
||||
|
||||
<a href="@Url.Action("Index", "Home")" class="btn btn-primary mt-1">@LayoutResource.back</a>
|
||||
7
Views/Home/Index.cshtml
Normal file
7
Views/Home/Index.cshtml
Normal file
@@ -0,0 +1,7 @@
|
||||
@using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
@using SimpleIdp.Resources
|
||||
|
||||
@{
|
||||
ViewBag.Title = HomeResource.home;
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
287
Views/Home/Profile.cshtml
Normal file
287
Views/Home/Profile.cshtml
Normal file
@@ -0,0 +1,287 @@
|
||||
@using Microsoft.AspNetCore.Http;
|
||||
@using SimpleIdServer.IdServer.Domains;
|
||||
@using SimpleIdp.Resources
|
||||
@using System.Security.Claims;
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.ProfileViewModel
|
||||
|
||||
@{
|
||||
ViewBag.Title = ProfileResource.title;
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
Func<string, string> getClaim = (str) =>
|
||||
{
|
||||
var cl = User.Claims.FirstOrDefault(c => c.Type == str);
|
||||
if (cl == null) return "-";
|
||||
return cl.Value;
|
||||
};
|
||||
var basePath = Context.Request.GetAbsoluteUriWithVirtualPath();
|
||||
var returnUrl = $"{basePath}{Url.Action("Profile", "Home")}";
|
||||
}
|
||||
|
||||
<div class="row profile gy-4">
|
||||
<!-- User Information -->
|
||||
<div class="col-md-3">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body info">
|
||||
<div class="picture">
|
||||
@Html.UserPicture(User, Model.Picture, true)
|
||||
<form id="pictureForm" action="@Url.Action("UpdatePicture", "Home")" method="post">
|
||||
<input type="file" id="pictureFile" name="File" style="display: none" accept="image/*" />
|
||||
</form>
|
||||
</div>
|
||||
<ul>
|
||||
<!-- Name identifier -->
|
||||
<li>
|
||||
<h6>@ProfileResource.subject</h6>
|
||||
<span class="text-muted">@getClaim(ClaimTypes.NameIdentifier)</span>
|
||||
</li>
|
||||
<!-- Name -->
|
||||
<li>
|
||||
<h6>@ProfileResource.name</h6>
|
||||
<span class="text-muted">@User.Identity.Name</span>
|
||||
</li>
|
||||
<!-- OTP Key -->
|
||||
<li>
|
||||
<h6>@ProfileResource.qrcode_otp</h6>
|
||||
@if (!Model.HasOtpKey)
|
||||
{
|
||||
<div class="alert alert-warning">@ProfileResource.no_otp</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div>
|
||||
<img src="@Url.Action("GetOTP", "Home")" width="200px" />
|
||||
</div>
|
||||
}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="row gy-4">
|
||||
<!-- OPENID Consents -->
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5>@ProfileResource.approved_apps_title</h5>
|
||||
<p>@ProfileResource.approved_apps_description</p>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>@ProfileResource.client</th>
|
||||
<th>@ProfileResource.scopes</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var consent in Model.Consents.OrderBy(c => c.ClientName))
|
||||
{
|
||||
<tr>
|
||||
<td>@Html.ClientPicture(consent.ClientUri)</td>
|
||||
<td class="align-middle">@(string.IsNullOrWhiteSpace(consent.ClientName) ? '-' : consent.ClientName)</td>
|
||||
<td class="align-middle">
|
||||
@if(consent.ScopeNames != null && consent.ScopeNames.Any())
|
||||
{
|
||||
foreach(var scopeName in consent.ScopeNames)
|
||||
{
|
||||
<span class="badge bg-secondary">@scopeName</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>-</span>
|
||||
}
|
||||
</td>
|
||||
<td class="align-middle">
|
||||
<a href="@Url.Action("RejectConsent", "Home", new { consentId = consent.ConsentId })" class="btn btn-danger">@ProfileResource.revoke_access</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Pending requests -->
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5>@ProfileResource.pending_request_title</h5>
|
||||
<p>@ProfileResource.pending_request_description</p>
|
||||
@if(Model.PendingRequests != null && Model.PendingRequests.Any())
|
||||
{
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>@ProfileResource.resource</th>
|
||||
<th>@ProfileResource.scopes</th>
|
||||
<th>@ProfileResource.requester</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var consent in Model.PendingRequests.Where(p => p.Owner == getClaim(ClaimTypes.NameIdentifier) && p.Status == UMAPendingRequestStatus.TOBECONFIRMED).OrderByDescending(u => u.CreateDateTime))
|
||||
{
|
||||
<tr>
|
||||
<td>@(string.IsNullOrWhiteSpace(consent.ResourceName) ? '-' : consent.ResourceName)</td>
|
||||
<td>
|
||||
@if(consent.Scopes != null && consent.Scopes.Any())
|
||||
{
|
||||
<span>-</span>
|
||||
}
|
||||
@foreach(var scope in consent.Scopes)
|
||||
{
|
||||
<span class="badge bg-secondary">@scope</span>
|
||||
}
|
||||
</td>
|
||||
<td>@consent.Requester</td>
|
||||
<td>
|
||||
<a href="@Url.Action("RejectUmaPendingRequest", "Home", new { ticketId = consent.TicketId})" class="btn btn-danger">@ProfileResource.revoke_access</a>
|
||||
<a href="@Url.Action("ConfirmUmaPendingRequest", "Home", new { ticketId = consent.TicketId})" class="btn btn-success">@ProfileResource.accept_access</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
else
|
||||
{
|
||||
<i>@ProfileResource.no_pending_request</i>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- External accounts -->
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5>@ProfileResource.external_accounts_title</h5>
|
||||
<p>@ProfileResource.external_accounts_description</p>
|
||||
@if (Model.Profiles != null && Model.Profiles.Any())
|
||||
{
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>@ProfileResource.account_name</th>
|
||||
<th>@ProfileResource.account_login</th>
|
||||
<th>@ProfileResource.created_at</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var externalAccount in Model.Profiles)
|
||||
{
|
||||
<tr>
|
||||
<td>@externalAccount.Scheme</td>
|
||||
<td>@externalAccount.Subject</td>
|
||||
<td>@externalAccount.CreateDateTime.ToString("dd/M/yyyy HH:mm:ss")</td>
|
||||
<td>
|
||||
|
||||
@using (Html.BeginForm("Unlink", "Home", FormMethod.Post))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" value="@externalAccount.Subject" name="Subject" />
|
||||
<input type="hidden" value="@externalAccount.Scheme" name="Scheme" />
|
||||
<button type="submit" class="btn btn-danger">@ProfileResource.unlink</button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
else
|
||||
{
|
||||
<i>@ProfileResource.no_external_accounts</i>
|
||||
}
|
||||
|
||||
<div class="mt-2">
|
||||
@foreach(var extProvider in Model.ExternalIdProviders)
|
||||
{
|
||||
<a class="btn btn-secondary me-1" href="@Url.Action("Link", "Home", new { scheme = extProvider.AuthenticationScheme, returnUrl = returnUrl })">
|
||||
@extProvider.DisplayName
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Manage credentials -->
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5>@ProfileResource.credentials</h5>
|
||||
<div>
|
||||
@if(Model.AuthenticationMethods != null && Model.AuthenticationMethods.Any(m => m.IsCredentialExists))
|
||||
{
|
||||
<p>@ProfileResource.update_your_credentials</p>
|
||||
foreach(var authenticationMethod in Model.AuthenticationMethods.Where(m => m.IsCredentialExists))
|
||||
{
|
||||
<a class="btn btn-secondary me-1" href="@Url.Action("RegisterCredential", "Home", new { name = authenticationMethod.Amr, redirectUrl = returnUrl })">
|
||||
@authenticationMethod.Name
|
||||
</a>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>@ProfileResource.no_credentials_to_update</p>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
@if(Model.AuthenticationMethods != null && Model.AuthenticationMethods.Any(m => !m.IsCredentialExists))
|
||||
{
|
||||
<p>@ProfileResource.enroll_credentials</p>
|
||||
foreach (var authenticationMethod in Model.AuthenticationMethods.Where(m => !m.IsCredentialExists))
|
||||
{
|
||||
<a class="btn btn-secondary me-1" href="@Url.Action("RegisterCredential", "Home", new { name = authenticationMethod.Amr, redirectUrl = returnUrl })">
|
||||
@authenticationMethod.Name
|
||||
</a>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>@ProfileResource.no_credentials_to_create</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$("#pictureFile").on("change", function (e) {
|
||||
const files = e.target.files;
|
||||
if (files.length != 1) return;
|
||||
const action = $("#pictureForm").attr("action");
|
||||
const formData = new FormData();
|
||||
formData.append('file', files[0]);
|
||||
$.ajax({
|
||||
url: action,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function() {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
$('#user-picture').attr('src', e.target.result);
|
||||
}
|
||||
|
||||
reader.readAsDataURL(files[0]);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$("#edit-profile").on('click', function () {
|
||||
$("#pictureFile").trigger('click');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
50
Views/Sessions/Index.cshtml
Normal file
50
Views/Sessions/Index.cshtml
Normal file
@@ -0,0 +1,50 @@
|
||||
@using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
@using SimpleIdServer.IdServer.Helpers
|
||||
@using SimpleIdp.Resources
|
||||
@model IEnumerable<SimpleIdServer.IdServer.UI.ViewModels.SessionViewModel>
|
||||
|
||||
@{
|
||||
ViewBag.Title = SessionsResource.title;
|
||||
Layout = "~/Views/Shared/_CommonLayout.cshtml";
|
||||
}
|
||||
|
||||
<nav class="navbar navbar-expand-lg bg-primary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#">
|
||||
<img src="~/images/SIDLogo.svg" width="40px" />
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="container">
|
||||
@if(Model.Any())
|
||||
{
|
||||
var grp = Model.GroupBy(g => g.Realm);
|
||||
foreach (var kvp in grp)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<h5>@string.Format(SessionsResource.realm, kvp.Key)</h5>
|
||||
<ul class="list-group">
|
||||
@foreach (var session in kvp)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<a href="@Url.Action("Index", "Home", new { prefix = kvp.Key })">@session.Name</a>
|
||||
<form action="@Url.Action("Index", "Sessions", new { realm = kvp.Key, user = session.Name })" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" name="Realm" value="@kvp.Key" />
|
||||
<input type="hidden" name="User" value="@session.Name" />
|
||||
<button type="submit" class="btn btn-danger"><i class="fa-solid fa-trash" style="padding-right:5px"></i>@SessionsResource.revoke</button>
|
||||
</form>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-danger">@SessionsResource.no_session</div>
|
||||
}
|
||||
</div>
|
||||
27
Views/Shared/_CommonLayout.cshtml
Normal file
27
Views/Shared/_CommonLayout.cshtml
Normal file
@@ -0,0 +1,27 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using SimpleIdp.Resources
|
||||
@using System.Globalization
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>SimpleIdServer - @ViewBag.Title</title>
|
||||
<link rel="stylesheet" href="@Url.Content("~/lib/bootstrap/css/bootstrap.css")" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/lib/fontawesome/css/all.css")" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/styles/theme.css")" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/styles/authenticate.css")" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/styles/consent.css")" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/styles/profile.css")" />
|
||||
<link rel="icon" href="@Url.Content("~/images/favicon.ico")" />
|
||||
</head>
|
||||
<body class="orange">
|
||||
@RenderBody()
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/jquery/jquery.js")"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/popper.js/umd/popper.js")"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/bootstrap/js/bootstrap.js")"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/helpers.js")"></script>
|
||||
@RenderSection("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
82
Views/Shared/_FormBuilderLayout.cshtml
Normal file
82
Views/Shared/_FormBuilderLayout.cshtml
Normal file
@@ -0,0 +1,82 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using FormBuilder.Components
|
||||
@using SimpleIdp.Resources
|
||||
@using System.Globalization
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.ILayoutViewModel
|
||||
@namespace FormBuilder.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@{
|
||||
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString}";
|
||||
var currentCultureInfo = CultureInfo.DefaultThreadCurrentUICulture;
|
||||
string languagesLabel = LayoutResource.ResourceManager.GetString("languages");
|
||||
if (currentCultureInfo != null && !string.IsNullOrWhiteSpace(currentCultureInfo.Name))
|
||||
{
|
||||
var str = LayoutResource.ResourceManager.GetString(currentCultureInfo.Name);
|
||||
if (!string.IsNullOrWhiteSpace(str))
|
||||
{
|
||||
languagesLabel = string.Format(LayoutResource.ResourceManager.GetString("selected_language"), str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="~/" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/lib/bootstrap/css/bootstrap.css")" />
|
||||
<link rel="stylesheet" href="@Url.Content("~/styles/theme.css")" />
|
||||
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css">
|
||||
<link rel="stylesheet" href="_content/SidFormBuilder/themes.css" />
|
||||
<link rel="stylesheet" href="_content/SidFormBuilder/style.css" />
|
||||
<link rel="stylesheet" href="FormBuilder.Startup.styles.css" />
|
||||
@RenderSection("Header", required: false)
|
||||
</head>
|
||||
<body class="orange">
|
||||
<nav class="navbar navbar-expand-lg bg-primary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#">
|
||||
<img src="~/images/SIDLogo.svg" width="40px" />
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<div class="me-auto"></div>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" data-bs-toggle="dropdown">
|
||||
@languagesLabel
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
@foreach (var language in Model.Languages)
|
||||
{
|
||||
<form asp-controller="Home" asp-action="SwitchLanguage" asp-area="" method="post">
|
||||
<input type="hidden" name="culture" value="@language.Code" />
|
||||
<input type="hidden" name="returnUrl" value="@returnUrl" />
|
||||
<button type="submit" class="dropdown-item" href="#">@language.Description</button>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@RenderBody()
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/jquery/jquery.js")"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/popper.js/umd/popper.js")"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/bootstrap/js/bootstrap.js")"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script src="_content/SidFormBuilder/lib.js"></script>
|
||||
<script src="_content/SidFormBuilder/reCaptcha.js"></script>
|
||||
<script src="_content/BlazorMonaco/jsInterop.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||
<script type="text/javascript" src="@Url.Content("~/lib/helpers.js")"></script>
|
||||
@RenderSection("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
97
Views/Shared/_Layout.cshtml
Normal file
97
Views/Shared/_Layout.cshtml
Normal file
@@ -0,0 +1,97 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using SimpleIdServer.IdServer.Options
|
||||
@using SimpleIdServer.IdServer.Resources
|
||||
@using SimpleIdp.Resources
|
||||
@using Microsoft.Extensions.Options
|
||||
@using System.Globalization
|
||||
@inject IOptions<IdServerHostOptions> options
|
||||
@model SimpleIdServer.IdServer.UI.ViewModels.ILayoutViewModel
|
||||
|
||||
@{
|
||||
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString}";
|
||||
var currentCultureInfo = CultureInfo.DefaultThreadCurrentUICulture;
|
||||
string languagesLabel = LayoutResource.ResourceManager.GetString("languages");
|
||||
if (currentCultureInfo != null && !string.IsNullOrWhiteSpace(currentCultureInfo.Name))
|
||||
{
|
||||
var str = LayoutResource.ResourceManager.GetString(currentCultureInfo.Name);
|
||||
if (!string.IsNullOrWhiteSpace(str))
|
||||
{
|
||||
languagesLabel = string.Format(LayoutResource.ResourceManager.GetString("selected_language"), str);
|
||||
}
|
||||
}
|
||||
Layout = "~/Views/Shared/_CommonLayout.cshtml";
|
||||
}
|
||||
|
||||
<nav class="navbar navbar-expand-lg bg-primary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#">
|
||||
<img src="~/images/SIDLogo.svg" width="40px" />
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto">
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="@Url.Action("Profile", "Home")">
|
||||
Welcome @User.Identity.Name
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
||||
@if (options.Value.RealmEnabled)
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="@Url.Action("Index", "Sessions", new { prefix = string.Empty })">
|
||||
@LayoutResource.Sessions
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
@RenderSection("SubMenu", required: false)
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="@Url.Action("Disconnect", "Home", new { area = "" })">@LayoutResource.disconnect</a>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="@Url.Action("Profile", "Home", new { area = "" })">@LayoutResource.authenticate</a>
|
||||
</li>
|
||||
}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" data-bs-toggle="dropdown">
|
||||
@languagesLabel
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
@foreach (var language in Model.Languages)
|
||||
{
|
||||
<form asp-controller="Home" asp-action="SwitchLanguage" asp-area="" method="post">
|
||||
<input type="hidden" name="culture" value="@language.Code" />
|
||||
<input type="hidden" name="returnUrl" value="@returnUrl" />
|
||||
<button type="submit" class="dropdown-item" href="#">@language.Description</button>
|
||||
</form>
|
||||
}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="container">
|
||||
<div>
|
||||
@RenderSection("PageTitle", false)
|
||||
</div>
|
||||
<div>
|
||||
@RenderBody()
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@RenderSection("Scripts", required: false)
|
||||
}
|
||||
Reference in New Issue
Block a user