This commit is contained in:
Jonathan Jenne
2024-01-16 09:44:48 +01:00
parent 0a01bf59ef
commit 6131948f2a
13 changed files with 223 additions and 61 deletions

View File

@@ -53,6 +53,12 @@ namespace EnvelopeGenerator.Web.Controllers
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
EnvelopeResponse response = envelopeService.LoadEnvelope(envelopeKey);
// Again check if receiver has already signed
if (envelopeService.ReceiverAlreadySigned(response.Envelope, response.Receiver.Id) == true)
{
return Problem(statusCode: 403);
}
var Request = ControllerContext.HttpContext.Request;
var document = envelopeService.GetDocument(Request, envelopeKey);

View File

@@ -19,10 +19,54 @@ namespace EnvelopeGenerator.Web.Controllers
[HttpGet]
[Route("/")]
public IActionResult Index()
{
List<Envelope> envelopes = _envelopeService.LoadEnvelopes();
{
return View();
}
return View(envelopes);
[HttpPost]
[Route("/")]
public IActionResult DebugEnvelopes()
{
try
{
StringValues passwordFromForm = HttpContext.Request.Form["password"];
string passwordFromConfig = database.GetAppSetting("Config:AdminPassword");
if (passwordFromConfig == null)
{
ViewData["error"] = "No admin password configured!";
return View("Index");
}
if (passwordFromForm.Count != 1)
{
ViewData["error"] = "No admin password configured!";
return View("Index");
}
string password = passwordFromForm[0];
if (password == null)
{
ViewData["error"] = "No password supplied!";
return View("Index");
}
if (password != passwordFromConfig)
{
ViewData["error"] = "Wrong Password!";
return View("Index");
}
List<Envelope> envelopes = _envelopeService.LoadEnvelopes();
return View(envelopes);
}
catch (Exception e)
{
ViewData["error"] = "Unknown error!";
return View("Index");
}
}
[HttpGet]

View File

@@ -6,6 +6,7 @@ namespace EnvelopeGenerator.Web.Services
public class DatabaseService: BaseService
{
public MSSQLServer MSSQL { get; set; }
public IConfiguration Config { get; set; }
public State State { get; set; }
@@ -47,12 +48,13 @@ namespace EnvelopeGenerator.Web.Services
public readonly ModelContainer? Models;
public readonly ServiceContainer? Services;
public DatabaseService(IConfiguration Config, LoggingService Logging) : base(Config, Logging)
public DatabaseService(IConfiguration pConfig, LoggingService pLogging) : base(pConfig, pLogging)
{
logger = Logging.LogConfig.GetLogger();
logger = pLogging.LogConfig.GetLogger();
Config = pConfig;
logger.Debug("Establishing MSSQL Database connection..");
MSSQL = new MSSQLServer(logConfig, Config["Config:ConnectionString"]);
MSSQL = new MSSQLServer(logConfig, pConfig["Config:ConnectionString"]);
if (MSSQL.DBInitialized == true)
{
@@ -71,6 +73,11 @@ namespace EnvelopeGenerator.Web.Services
}
}
public string? GetAppSetting(string key)
{
return Config[key];
}
/// <summary>
/// There is a circular dependency between state and models
/// All models need a state object, including the config Model

View File

@@ -0,0 +1,48 @@
@using EnvelopeGenerator.Common;
@using static EnvelopeGenerator.Common.Constants;
@{
ViewData["Title"] = "Debug";
}
@functions {
string encodeEnvelopeKey(Envelope envelope)
{
var receiver = envelope.Receivers.First();
return Helpers.EncodeEnvelopeReceiverId(envelope.Uuid, receiver.Signature);
}
IEnumerable<IGrouping<EnvelopeStatus, Envelope>> groupEnvelopes(List<Envelope> envelopes)
{
return envelopes.GroupBy(item => item.Status).OrderBy(item => (int)item.Key);
}
}
<div class="container">
<section>
@foreach (IGrouping<EnvelopeStatus, Envelope> group in groupEnvelopes((List<Envelope>)@Model))
{
<section>
<h2>@group.Key.ToString() @group.Count()</h2>
<details>
<summary>Show envelopes</summary>
@foreach (Envelope envelope in @group)
{
<section>
<article class="envelope">
<strong><a href="/EnvelopeKey/@encodeEnvelopeKey(envelope)">@envelope.Title</a></strong>
<div><strong>Ersteller</strong> @envelope.User.Email</div>
<div><strong>Datum</strong> @envelope.AddedWhen</div>
</article>
</section>
}
</details>
<hr />
</section>
}
</section>
</div>

View File

@@ -2,9 +2,9 @@
ViewData["Title"] = "Dokument geschützt";
}
<div id="page-locked" class="container p-5">
<div class="page container p-5">
<header class="text-center">
<div class="icon bg-warning text-black">
<div class="icon locked">
<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" fill="currentColor" class="bi bi-shield-lock" viewBox="0 0 16 16">
<path d="M5.338 1.59a61 61 0 0 0-2.837.856.48.48 0 0 0-.328.39c-.554 4.157.726 7.19 2.253 9.188a10.7 10.7 0 0 0 2.287 2.233c.346.244.652.42.893.533q.18.085.293.118a1 1 0 0 0 .101.025 1 1 0 0 0 .1-.025q.114-.034.294-.118c.24-.113.547-.29.893-.533a10.7 10.7 0 0 0 2.287-2.233c1.527-1.997 2.807-5.031 2.253-9.188a.48.48 0 0 0-.328-.39c-.651-.213-1.75-.56-2.837-.855C9.552 1.29 8.531 1.067 8 1.067c-.53 0-1.552.223-2.662.524zM5.072.56C6.157.265 7.31 0 8 0s1.843.265 2.928.56c1.11.3 2.229.655 2.887.87a1.54 1.54 0 0 1 1.044 1.262c.596 4.477-.787 7.795-2.465 9.99a11.8 11.8 0 0 1-2.517 2.453 7 7 0 0 1-1.048.625c-.28.132-.581.24-.829.24s-.548-.108-.829-.24a7 7 0 0 1-1.048-.625 11.8 11.8 0 0 1-2.517-2.453C1.928 10.487.545 7.169 1.141 2.692A1.54 1.54 0 0 1 2.185 1.43 63 63 0 0 1 5.072.56" />
<path d="M9.5 6.5a1.5 1.5 0 0 1-1 1.415l.385 1.99a.5.5 0 0 1-.491.595h-.788a.5.5 0 0 1-.49-.595l.384-1.99a1.5 1.5 0 1 1 2-1.415" />
@@ -18,7 +18,7 @@
</section>
<section>
<form id="form-access-code" method="post">
<form id="form-access-code" class="form" method="post">
<div class="input">
<label class="visually-hidden" for="access_code">Zugriffscode</label>
<input type="password" class="form-control" name="access_code" placeholder="Zugriffscode" required="required">
@@ -36,4 +36,6 @@
<p>Bitte überprüfen Sie Ihr Email Postfach inklusive Spam-Ordner. Sie können auch den Absender bitten, Ihnen den Code auf anderem Wege zukommen zu lassen.</p>
</details>
</section>
</div>
</div>
<footer class="container" id="page-footer">&copy; SignFlow 2023-2024 <a href="https://digitaldata.works">Digital Data GmbH</a></footer>

View File

@@ -2,9 +2,9 @@
ViewData["Title"] = "Dokument unterschrieben";
}
<div id="page-success" class="container p-5">
<div class="page container p-5">
<header class="text-center">
<div class="icon bg-success text-light">
<div class="icon signed">
<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" fill="currentColor" class="bi bi-check2-circle" viewBox="0 0 16 16">
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z" />
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z" />
@@ -19,3 +19,5 @@
</div>
<footer class="container" id="page-footer">&copy; SignFlow 2023-2024 <a href="https://digitaldata.works">Digital Data GmbH</a></footer>

View File

@@ -1,33 +1,37 @@
@using EnvelopeGenerator.Common;
@using static EnvelopeGenerator.Common.Constants;
@{
ViewData["Title"] = "Home Page";
@{
ViewData["Title"] = "Dokument geschützt";
}
@functions {
string encodeEnvelopeKey(Envelope envelope)
<div class="page container p-5">
<header class="text-center">
<div class="icon admin">
<svg xmlns="http://www.w3.org/2000/svg" width="72" height="72" fill="currentColor" class="bi bi-cup-hot" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M.5 6a.5.5 0 0 0-.488.608l1.652 7.434A2.5 2.5 0 0 0 4.104 16h5.792a2.5 2.5 0 0 0 2.44-1.958l.131-.59a3 3 0 0 0 1.3-5.854l.221-.99A.5.5 0 0 0 13.5 6zM13 12.5a2 2 0 0 1-.316-.025l.867-3.898A2.001 2.001 0 0 1 13 12.5M2.64 13.825 1.123 7h11.754l-1.517 6.825A1.5 1.5 0 0 1 9.896 15H4.104a1.5 1.5 0 0 1-1.464-1.175" />
<path d="m4.4.8-.003.004-.014.019a4 4 0 0 0-.204.31 2 2 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.6.6 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3 3 0 0 1-.202.388 5 5 0 0 1-.253.382l-.018.025-.005.008-.002.002A.5.5 0 0 1 3.6 4.2l.003-.004.014-.019a4 4 0 0 0 .204-.31 2 2 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.6.6 0 0 0-.09-.252A4 4 0 0 0 3.6 2.8l-.01-.012a5 5 0 0 1-.37-.543A1.53 1.53 0 0 1 3 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a6 6 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 4.4.8m3 0-.003.004-.014.019a4 4 0 0 0-.204.31 2 2 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.6.6 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3 3 0 0 1-.202.388 5 5 0 0 1-.253.382l-.018.025-.005.008-.002.002A.5.5 0 0 1 6.6 4.2l.003-.004.014-.019a4 4 0 0 0 .204-.31 2 2 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.6.6 0 0 0-.09-.252A4 4 0 0 0 6.6 2.8l-.01-.012a5 5 0 0 1-.37-.543A1.53 1.53 0 0 1 6 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a6 6 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 7.4.8m3 0-.003.004-.014.019a4 4 0 0 0-.204.31 2 2 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.6.6 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3 3 0 0 1-.202.388 5 5 0 0 1-.252.382l-.019.025-.005.008-.002.002A.5.5 0 0 1 9.6 4.2l.003-.004.014-.019a4 4 0 0 0 .204-.31 2 2 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.6.6 0 0 0-.09-.252A4 4 0 0 0 9.6 2.8l-.01-.012a5 5 0 0 1-.37-.543A1.53 1.53 0 0 1 9 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a6 6 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 10.4.8" />
</svg>
</div>
<h1>Administration</h1>
</header>
@if (ViewData["error"] != null)
{
var receiver = envelope.Receivers.First();
return Helpers.EncodeEnvelopeReceiverId(envelope.Uuid, receiver.Signature);
<section class="alert alert-danger">
@ViewData["error"]
</section>
}
}
<div class="container">
<section>
@foreach (IGrouping<EnvelopeStatus, Envelope> group in ((List<Envelope>)@Model).GroupBy(item => item.Status).OrderBy(item => (int)item.Key))
{
<section>
<h2>@group.Key.ToString()</h2>
<form id="form-access-code" class="form" method="post">
<div class="input">
<label class="visually-hidden" for="access_code">Passwort</label>
<input type="password" class="form-control" name="password" placeholder="Passwort" required="required">
</div>
<ul>
@foreach (Envelope envelope in @group)
{
<li><a href="/EnvelopeKey/@encodeEnvelopeKey(envelope)">@envelope.Title</a></li>
}
</ul>
<hr />
</section>
}
<div class="button">
<button type="submit" class="btn btn-primary">Öffnen</button>
</div>
</form>
</section>
</div>
<footer class="container" id="page-footer">&copy; SignFlow 2023-2024 <a href="https://digitaldata.works">Digital Data GmbH</a></footer>

View File

@@ -10,6 +10,7 @@
"ConnectionString": "Server=sDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;",
"LogPath": "E:\\EnvelopeGenerator\\Logs",
"LogDebug": true,
"LogJson": true
"LogJson": true,
"AdminPassword": "dd"
}
}

View File

@@ -41,26 +41,46 @@
color: white;
}
body {
background-color: #bbb;
}
/* Success Page */
.page {
margin-top: 3rem;
background: white;
border-radius: 5px;
box-shadow: rgba(9, 30, 66, 0.25) 0px 4px 8px -2px, rgba(9, 30, 66, 0.08) 0px 0px 0px 1px;
max-width: 40rem;
}
#page-success header .icon {
.page section {
max-width: 30rem;
margin: 0 auto;
}
.page header .icon {
display: inline-block;
border-radius: 100px;
padding: 15px;
margin-bottom: 2rem;
}
/* Locked Page */
.page header .icon.admin {
background-color: #331904;
color: #fecba1;
}
#page-locked header .icon {
display: inline-block;
border-radius: 10px;
padding: 15px;
margin-bottom: 2rem;
}
.page header .icon.locked {
background-color: #ffc107;
color: #000;
}
#form-access-code {
.page header .icon.signed {
background-color: #146c43;
color: #fff;
}
.page .form {
max-width: 30rem;
margin: 2rem auto;
@@ -68,7 +88,35 @@
gap: 1rem;
}
#form-access-code > .input {
#form-access-code > .input,
#form-admin-password > .input {
flex-grow: 1;
}
#page-admin header .icon {
background-color: #331904;
color: #fecba1;
}
.envelope {
display: block;
border: 1px solid #eee;
margin-bottom: 1rem;
padding: 0.5rem;
}
footer#page-footer {
color: #333;
max-width: 40rem;
margin-top: 1rem;
font-size: 0.85rem;
}
footer#page-footer a,
footer#page-footer a:link,
footer#page-footer a:hover,
footer#page-footer a:visited,
footer#page-footer a:focus {
color: #444;
}