Add structured logging to IntranetController actions
Extensive structured logging was added throughout IntranetController and all invoice/account handlers to improve traceability and debugging. Logging now covers action entry/exit, error conditions, and key parameters (user IDs, invoice IDs, etc.). Handlers log warnings for missing/invalid input and info/debug for significant events. Minor refactoring extracts form values for better logging. The jQuery `rwText` plugin was hardened against null input. Updated minified JS, font assets, and OCORE submodule. No functional changes to `tools.js`.
This commit is contained in:
@@ -17,34 +17,51 @@ public partial class IntranetController
|
||||
{
|
||||
private async Task<IActionResult> Do_Process_Invoices(string fn, string id, string code)
|
||||
{
|
||||
_logger.LogDebug("Do_Process_Invoices called: fn={Fn} id={Id} code={Code} user={User}", fn, id, code, UserAccountID);
|
||||
|
||||
switch (id.ToLower())
|
||||
{
|
||||
case "auth":
|
||||
_logger.LogDebug("Invoice auth check for user {User}", UserAccountID);
|
||||
return await JSONAsync(new { manage = 1 });
|
||||
|
||||
case "setpyd":
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
return await setSQLValue_async(
|
||||
"EXECUTE [dbo].[fds__setInvoicePayed] @Id, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@Id", Form("id"))),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code))
|
||||
? Ok() : StatusCode(500);
|
||||
if (!HasForm("id")) { _logger.LogWarning("setpyd: missing form field 'id', user={User}", UserAccountID); return BadRequest400(); }
|
||||
{
|
||||
var invoiceId = Form("id");
|
||||
_logger.LogInformation("setpyd: marking invoice {InvoiceId} as paid, user={User}", invoiceId, UserAccountID);
|
||||
var ok = await setSQLValue_async(
|
||||
"EXECUTE [dbo].[fds__setInvoicePayed] @Id, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@Id", invoiceId)),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
if (!ok) _logger.LogError("setpyd: SQL failed for invoice {InvoiceId}, user={User}", invoiceId, UserAccountID);
|
||||
return ok ? Ok() : StatusCode(500);
|
||||
}
|
||||
|
||||
case "setupd":
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
return await setSQLValue_async(
|
||||
"EXECUTE [dbo].[fds__setInvoiceUNPayed] @Id, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@Id", Form("id"))),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code))
|
||||
? Ok() : StatusCode(500);
|
||||
if (!HasForm("id")) { _logger.LogWarning("setupd: missing form field 'id', user={User}", UserAccountID); return BadRequest400(); }
|
||||
{
|
||||
var invoiceId = Form("id");
|
||||
_logger.LogInformation("setupd: marking invoice {InvoiceId} as unpaid, user={User}", invoiceId, UserAccountID);
|
||||
var ok = await setSQLValue_async(
|
||||
"EXECUTE [dbo].[fds__setInvoiceUNPayed] @Id, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@Id", invoiceId)),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
if (!ok) _logger.LogError("setupd: SQL failed for invoice {InvoiceId}, user={User}", invoiceId, UserAccountID);
|
||||
return ok ? Ok() : StatusCode(500);
|
||||
}
|
||||
|
||||
case "setvat":
|
||||
if (!float.TryParse(Form("val").Replace("%", "").Replace(",", ".").Trim(),
|
||||
NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out float vatVal))
|
||||
return BadRequest400();
|
||||
{
|
||||
_logger.LogWarning("setvat: invalid VAT value '{Val}', user={User}", Form("val"), UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
{
|
||||
_logger.LogInformation("setvat: setting VAT {Vat} on report {ReportId}, user={User}", vatVal, Form("id"), UserAccountID);
|
||||
var pl = StdParamlist(
|
||||
SQL_BigInt("@id", Form("id")),
|
||||
SQL_VarChar("@entitytype", "report"),
|
||||
@@ -53,42 +70,90 @@ public partial class IntranetController
|
||||
string sqlEx = ""; int? sqlCode = null;
|
||||
setSQLValue("EXECUTE [dbo].[fds__setReportVAT] @id, @entitytype, @vat, @authuser;",
|
||||
_intranet.Intranet_SqlCon(), ref sqlEx, ref sqlCode, pl, Security: DbSec);
|
||||
if (!string.IsNullOrEmpty(sqlEx))
|
||||
_logger.LogError("setvat: SQL error for report {ReportId}: {SqlError}, user={User}", Form("id"), sqlEx, UserAccountID);
|
||||
return string.IsNullOrEmpty(sqlEx) ? Ok() : StatusCode(500, new { error = sqlEx });
|
||||
}
|
||||
|
||||
case "sis":
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("sis: missing form field 'id', user={User}", UserAccountID); return BadRequest400(); }
|
||||
{
|
||||
var pl = StdParamlist(SQL_VarChar("@Id", Form("id")), SQL_Bit("@auto", false));
|
||||
var invoiceId = Form("id");
|
||||
_logger.LogInformation("sis: marking invoice {InvoiceId} as sent, user={User}", invoiceId, UserAccountID);
|
||||
var pl = StdParamlist(SQL_VarChar("@Id", invoiceId), SQL_Bit("@auto", false));
|
||||
var dt2 = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__setInvoiceSent] @Id, @auto, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString, pl,
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
if (!string.IsNullOrEmpty(dt2.Exception))
|
||||
_logger.LogError("sis: SQL error for invoice {InvoiceId}: {SqlError}, user={User}", invoiceId, dt2.Exception, UserAccountID);
|
||||
return string.IsNullOrEmpty(dt2.Exception) ? Ok() : StatusCode(500);
|
||||
}
|
||||
|
||||
case "pget": return await HandleInvoicePget(fn, id, code);
|
||||
case "get": return await HandleInvoiceGet(fn, id, code);
|
||||
case "icget": return await HandleInvoiceIcGet(fn, id, code);
|
||||
case "pget":
|
||||
_logger.LogDebug("pget: invoice PDF get, user={User}", UserAccountID);
|
||||
return await HandleInvoicePget(fn, id, code);
|
||||
|
||||
case "get":
|
||||
_logger.LogDebug("get: invoice get, user={User}", UserAccountID);
|
||||
return await HandleInvoiceGet(fn, id, code);
|
||||
|
||||
case "icget":
|
||||
_logger.LogDebug("icget: invoice IC get, user={User}", UserAccountID);
|
||||
return await HandleInvoiceIcGet(fn, id, code);
|
||||
|
||||
case "storno":
|
||||
case "credit": return await HandleInvoiceStornoCredit(fn, id, code);
|
||||
case "invl": return await HandleInvoiceList(fn, id, code);
|
||||
case "rqi": return await HandleInvoiceRequestItems(fn, id, code);
|
||||
case "pyi": return await HandleInvoicePayments(fn, id, code);
|
||||
case "datev": return await HandleDatev(fn, id, code);
|
||||
case "rdoc": return await HandleReportDoc(fn, id, code, Form("id"));
|
||||
case "rdocn": return await HandleReportDocByName(fn, id, code);
|
||||
case "datevzip": return await HandleDatevZip(fn, id, code);
|
||||
case "getrem": return await HandleGetReminder(fn, id, code);
|
||||
case "credit":
|
||||
_logger.LogInformation("{Action}: invoice storno/credit, user={User}", id, UserAccountID);
|
||||
return await HandleInvoiceStornoCredit(fn, id, code);
|
||||
|
||||
case "invl":
|
||||
_logger.LogDebug("invl: invoice list, user={User}", UserAccountID);
|
||||
return await HandleInvoiceList(fn, id, code);
|
||||
|
||||
case "rqi":
|
||||
_logger.LogDebug("rqi: invoice request items, user={User}", UserAccountID);
|
||||
return await HandleInvoiceRequestItems(fn, id, code);
|
||||
|
||||
case "pyi":
|
||||
_logger.LogDebug("pyi: invoice payments, user={User}", UserAccountID);
|
||||
return await HandleInvoicePayments(fn, id, code);
|
||||
|
||||
case "datev":
|
||||
_logger.LogDebug("datev: DATEV export, user={User}", UserAccountID);
|
||||
return await HandleDatev(fn, id, code);
|
||||
|
||||
case "rdoc":
|
||||
_logger.LogDebug("rdoc: report document get id={DocId}, user={User}", Form("id"), UserAccountID);
|
||||
return await HandleReportDoc(fn, id, code, Form("id"));
|
||||
|
||||
case "rdocn":
|
||||
_logger.LogDebug("rdocn: report document get by name, user={User}", UserAccountID);
|
||||
return await HandleReportDocByName(fn, id, code);
|
||||
|
||||
case "datevzip":
|
||||
_logger.LogDebug("datevzip: DATEV ZIP export, user={User}", UserAccountID);
|
||||
return await HandleDatevZip(fn, id, code);
|
||||
|
||||
case "getrem":
|
||||
_logger.LogDebug("getrem: get reminder for invoice, user={User}", UserAccountID);
|
||||
return await HandleGetReminder(fn, id, code);
|
||||
|
||||
case "mfrrel":
|
||||
if (!HasForm("id") || !long.TryParse(Form("id"), out long relId)) return BadRequest400();
|
||||
if (!HasForm("id") || !long.TryParse(Form("id"), out long relId))
|
||||
{
|
||||
_logger.LogWarning("mfrrel: missing or invalid form field 'id', user={User}", UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
_logger.LogInformation("mfrrel: resetting MFR relation for invoice {InvoiceId}, user={User}", relId, UserAccountID);
|
||||
using (var mfr = new fds.FdsMfrClient())
|
||||
await mfr.Update__entitytable(EntityTypes.Invoice,
|
||||
fds.FdsMfr.UpdateNeed.Reset, new[] { relId });
|
||||
return Ok();
|
||||
|
||||
default: return Ok();
|
||||
default:
|
||||
_logger.LogWarning("Do_Process_Invoices: unhandled action id={Id}, user={User}", id, UserAccountID);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,16 @@ public partial class IntranetController
|
||||
{
|
||||
private async Task<IActionResult> HandleInvoicePget(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!long.TryParse(Form("id"), out long tgtid)) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("HandleInvoicePget: missing 'id' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
if (!long.TryParse(Form("id"), out long tgtid)) { _logger.LogWarning("HandleInvoicePget: invalid 'id' value='{Value}' user={User}", Form("id"), UserAccountID); return BadRequest400(); }
|
||||
_logger.LogDebug("HandleInvoicePget tgtid={TgtId} user={User}", tgtid, UserAccountID);
|
||||
|
||||
using (var mfr = new fds.FdsMfrClient())
|
||||
{
|
||||
_logger.LogDebug("HandleInvoicePget resetting invoice entity tgtid={TgtId}", tgtid);
|
||||
await mfr.Update__entitytable(EntityTypes.Invoice,
|
||||
fds.FdsMfr.UpdateNeed.Reset, new[] { tgtid });
|
||||
}
|
||||
|
||||
var dt = await getSQLDatatable_async(
|
||||
"SELECT * FROM [dbo].[fds__getInvoiceTreeIds](@srqid);",
|
||||
@@ -30,6 +35,7 @@ public partial class IntranetController
|
||||
StdParamlist(SQL_BigInt("@srqid", tgtid)),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
|
||||
_logger.LogDebug("HandleInvoicePget tree query returned {Count} rows for tgtid={TgtId}", dt.Count, tgtid);
|
||||
if (dt.Count > 0)
|
||||
{
|
||||
var invIds = new List<long>();
|
||||
@@ -43,11 +49,14 @@ public partial class IntranetController
|
||||
case "servicerequest": if (iid > 0 && !srqIds.Contains(iid)) srqIds.Add(iid); break;
|
||||
}
|
||||
}
|
||||
_logger.LogDebug("HandleInvoicePget resetting {InvCount} invoices and {SrqCount} service requests", invIds.Count, srqIds.Count);
|
||||
using var mfr2 = new fds.FdsMfrClient();
|
||||
foreach (var iid in invIds)
|
||||
await mfr2.Update__entitytable(EntityTypes.Invoice, fds.FdsMfr.UpdateNeed.Reset, new[] { iid });
|
||||
foreach (var iid in srqIds)
|
||||
await mfr2.Update__entitytable(EntityTypes.ServiceRequest, fds.FdsMfr.UpdateNeed.Reset, new[] { iid });
|
||||
_logger.LogInformation("HandleInvoicePget reset complete for tgtid={TgtId} invoices={InvCount} serviceRequests={SrqCount} user={User}",
|
||||
tgtid, invIds.Count, srqIds.Count, UserAccountID);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
@@ -56,35 +65,48 @@ public partial class IntranetController
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("HandleInvoiceGet: missing 'id' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string invoiceId = Form("id");
|
||||
_logger.LogDebug("HandleInvoiceGet invoiceId={InvoiceId} user={User}", invoiceId, UserAccountID);
|
||||
var sqldset = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__getInvoice] @Id, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@Id", Form("id"))),
|
||||
StdParamlist(SQL_VarChar("@Id", invoiceId)),
|
||||
tablenames: new[] { "admin", "inv", "req", "itm" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
|
||||
var ldic = BuildInvoiceRequestList(sqldset);
|
||||
var adminDic = sqldset.Table("admin").FirstRow.toObjectDictionary();
|
||||
var invDic = sqldset.Table("inv").FirstRow.toObjectDictionary();
|
||||
if (invDic.nz("InvoiceOptions", "").Split(',').Contains("§13b"))
|
||||
bool has13b = invDic.nz("InvoiceOptions", "").Split(',').Contains("§13b");
|
||||
if (has13b)
|
||||
adminDic["p13b"] = true;
|
||||
_logger.LogDebug("HandleInvoiceGet invoiceId={InvoiceId} requestCount={ReqCount} has13b={Has13b} user={User}",
|
||||
invoiceId, ldic.Count, has13b, UserAccountID);
|
||||
return await JSONAsync(new { admin = adminDic, inv = invDic, req = ldic });
|
||||
}
|
||||
catch { return StatusCode(500); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "HandleInvoiceGet failed for id={InvoiceId} user={User}", Form("id"), UserAccountID);
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleInvoiceIcGet(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("HandleInvoiceIcGet: missing 'id' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string invoiceId = Form("id");
|
||||
_logger.LogDebug("HandleInvoiceIcGet (storno/recreate prep) invoiceId={InvoiceId} user={User}", invoiceId, UserAccountID);
|
||||
var sqldset = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__prepStorno_recreate] @InvId, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@InvId", Form("id"))),
|
||||
StdParamlist(SQL_VarChar("@InvId", invoiceId)),
|
||||
tablenames: new[] { "admin", "requests", "items", "steps", "companies", "locations" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
|
||||
var ldic = BuildRequestItemList(sqldset);
|
||||
_logger.LogDebug("HandleInvoiceIcGet invoiceId={InvoiceId} requestCount={ReqCount} user={User}",
|
||||
invoiceId, ldic.Count, UserAccountID);
|
||||
return await JSONAsync(new
|
||||
{
|
||||
admin = sqldset.Table("admin").FirstRow.toObjectDictionary(),
|
||||
@@ -96,34 +118,47 @@ public partial class IntranetController
|
||||
|
||||
private async Task<IActionResult> HandleInvoiceStornoCredit(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("id", "mode")) return BadRequest400();
|
||||
string sqlcmd = Form("mode") switch
|
||||
if (!HasForm("id", "mode")) { _logger.LogWarning("HandleInvoiceStornoCredit: missing required form fields user={User}", UserAccountID); return BadRequest400(); }
|
||||
string invoiceId = Form("id");
|
||||
string mode = Form("mode");
|
||||
_logger.LogDebug("HandleInvoiceStornoCredit invoiceId={InvoiceId} mode={Mode} user={User}", invoiceId, mode, UserAccountID);
|
||||
string sqlcmd = mode switch
|
||||
{
|
||||
"credit" => "EXECUTE [dbo].[fds__createCredit_simple] @Id, @authuser;",
|
||||
"simple" => "EXECUTE [dbo].[fds__createStorno_simple] @Id, @authuser;",
|
||||
"copy" => "EXECUTE [dbo].[fds__createStorno_copy] @Id, @authuser;",
|
||||
_ => ""
|
||||
};
|
||||
if (string.IsNullOrEmpty(sqlcmd)) return StatusCode(500, new { error = "function not allowed" });
|
||||
if (string.IsNullOrEmpty(sqlcmd))
|
||||
{
|
||||
_logger.LogWarning("HandleInvoiceStornoCredit: unknown mode={Mode} invoiceId={InvoiceId} user={User}", mode, invoiceId, UserAccountID);
|
||||
return StatusCode(500, new { error = "function not allowed" });
|
||||
}
|
||||
_logger.LogInformation("HandleInvoiceStornoCredit executing mode={Mode} invoiceId={InvoiceId} user={User}", mode, invoiceId, UserAccountID);
|
||||
var sqldset = await getSQLDataSet_async(sqlcmd,
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@Id", Form("id"))),
|
||||
StdParamlist(SQL_VarChar("@Id", invoiceId)),
|
||||
tablenames: new[] { "admin", "inv", "req", "itm" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
var reqList = BuildInvoiceRequestList(sqldset);
|
||||
_logger.LogDebug("HandleInvoiceStornoCredit complete mode={Mode} invoiceId={InvoiceId} requestCount={ReqCount} user={User}",
|
||||
mode, invoiceId, reqList.Count, UserAccountID);
|
||||
return await JSONAsync(new
|
||||
{
|
||||
admin = sqldset.Table("admin").FirstRow.toObjectDictionary(),
|
||||
inv = sqldset.Table("inv").FirstRow.toObjectDictionary(),
|
||||
req = BuildInvoiceRequestList(sqldset)
|
||||
req = reqList
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleInvoiceList(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("mode")) return BadRequest400();
|
||||
if (!HasForm("mode")) { _logger.LogWarning("HandleInvoiceList: missing 'mode' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string mode = Form("mode").ToLower();
|
||||
_logger.LogDebug("HandleInvoiceList mode={Mode} tgt={Tgt} user={User}", mode, Form("tgt"), UserAccountID);
|
||||
if (mode == "s" && Form("tgt").Contains(':'))
|
||||
{
|
||||
_logger.LogDebug("HandleInvoiceList using search path mode={Mode} search={Search} user={User}", mode, Form("tgt"), UserAccountID);
|
||||
var pl = StdParamlist(
|
||||
SQL_Date("@tgtdate", DBNull.Value),
|
||||
SQL_VarChar("@mode", Form("mode").ne("m")),
|
||||
@@ -134,6 +169,8 @@ public partial class IntranetController
|
||||
_intranet.Intranet__SQLConnectionString, pl,
|
||||
tablenames: new[] { "admin", "invoices" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
_logger.LogDebug("HandleInvoiceList search returned {Count} invoices user={User}",
|
||||
dset.Tables("invoices").Rows.Count, UserAccountID);
|
||||
return await JSONAsync(new
|
||||
{
|
||||
admin = dset.Table("admin").FirstRow.toObjectDictionary(),
|
||||
@@ -142,17 +179,25 @@ public partial class IntranetController
|
||||
}
|
||||
if (!DateTime.TryParseExact(Form("tgt"), "yy-MM-dd",
|
||||
CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var tgtdate))
|
||||
return BadRequest400();
|
||||
{
|
||||
_logger.LogWarning("HandleInvoiceList: invalid date format tgt='{Tgt}' user={User}", Form("tgt"), UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
{
|
||||
string includes = Form("includes").ne(Form("all") == "true" ? "all" : "");
|
||||
_logger.LogDebug("HandleInvoiceList date-based tgtdate={TgtDate} mode={Mode} includes={Includes} user={User}",
|
||||
tgtdate.ToString("yy-MM-dd"), mode, includes, UserAccountID);
|
||||
var pl = StdParamlist(
|
||||
SQL_Date("@tgtdate", tgtdate),
|
||||
SQL_VarChar("@mode", Form("mode").ne("m")),
|
||||
SQL_VarChar("@includes", Form("includes").ne(Form("all") == "true" ? "all" : "")));
|
||||
SQL_VarChar("@includes", includes));
|
||||
var dset = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__getInvoices_list_vario] @tgtdate, @mode, @includes, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString, pl,
|
||||
tablenames: new[] { "admin", "invoices" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
_logger.LogDebug("HandleInvoiceList date-based returned {Count} invoices user={User}",
|
||||
dset.Tables("invoices").Rows.Count, UserAccountID);
|
||||
return await JSONAsync(new
|
||||
{
|
||||
admin = dset.Table("admin").FirstRow.toObjectDictionary(),
|
||||
@@ -163,11 +208,13 @@ public partial class IntranetController
|
||||
|
||||
private async Task<IActionResult> HandleInvoiceRequestItems(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("HandleInvoiceRequestItems: missing 'id' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string invoiceId = Form("id");
|
||||
_logger.LogDebug("HandleInvoiceRequestItems invoiceId={InvoiceId} user={User}", invoiceId, UserAccountID);
|
||||
var sqldt = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__getInvRequestItems] @invoiceid, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@invoiceid", Form("id"))),
|
||||
StdParamlist(SQL_VarChar("@invoiceid", invoiceId)),
|
||||
tablenames: new[] { "requests", "items" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
var ldic = new List<Dictionary<string, object?>>();
|
||||
@@ -180,18 +227,25 @@ public partial class IntranetController
|
||||
.Select(r => r.toObjectDictionary()).ToList();
|
||||
ldic.Add(sdic!);
|
||||
}
|
||||
_logger.LogDebug("HandleInvoiceRequestItems invoiceId={InvoiceId} requestCount={ReqCount} user={User}",
|
||||
invoiceId, ldic.Count, UserAccountID);
|
||||
return await JSONAsync(new { requests = ldic });
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleInvoicePayments(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("HandleInvoicePayments: missing 'id' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string invoiceId = Form("id");
|
||||
_logger.LogDebug("HandleInvoicePayments invoiceId={InvoiceId} user={User}", invoiceId, UserAccountID);
|
||||
var sqldt = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__getInvPayments] @invoiceid, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@invoiceid", Form("id"))),
|
||||
StdParamlist(SQL_VarChar("@invoiceid", invoiceId)),
|
||||
tablenames: new[] { "items" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
int paymentCount = sqldt.Tables("items").Rows.Count;
|
||||
_logger.LogDebug("HandleInvoicePayments invoiceId={InvoiceId} paymentCount={PaymentCount} user={User}",
|
||||
invoiceId, paymentCount, UserAccountID);
|
||||
return await JSONAsync(new { payments = sqldt.Tables("items").toArrayofObjectDictionaries() });
|
||||
}
|
||||
|
||||
@@ -199,13 +253,20 @@ public partial class IntranetController
|
||||
{
|
||||
if (!DateTime.TryParseExact(Form("tgt"), "yy-MM-dd",
|
||||
CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var tgtdate))
|
||||
{
|
||||
_logger.LogWarning("HandleDatev: invalid date format tgt='{Tgt}' user={User}", Form("tgt"), UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
string mode = Form("mode").ne("m");
|
||||
_logger.LogDebug("HandleDatev tgtdate={TgtDate} mode={Mode} user={User}", tgtdate.ToString("yy-MM-dd"), mode, UserAccountID);
|
||||
var dset = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__getDatevExports] @tgtdate, @mode, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_Date("@tgtdate", tgtdate), SQL_VarChar("@mode", Form("mode").ne("m"))),
|
||||
StdParamlist(SQL_Date("@tgtdate", tgtdate), SQL_VarChar("@mode", mode)),
|
||||
tablenames: new[] { "files", "invoices", "debits" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
_logger.LogDebug("HandleDatev tgtdate={TgtDate} files={FileCount} invoices={InvCount} user={User}",
|
||||
tgtdate.ToString("yy-MM-dd"), dset.Tables("files").Rows.Count, dset.Tables("invoices").Rows.Count, UserAccountID);
|
||||
return await JSONAsync(new
|
||||
{
|
||||
files = dset.Tables("files").toArrayofObjectDictionaries(),
|
||||
@@ -215,9 +276,16 @@ public partial class IntranetController
|
||||
|
||||
private async Task<IActionResult> HandleReportDoc(string fn, string id, string code, string reportid)
|
||||
{
|
||||
_logger.LogDebug("HandleReportDoc reportid={ReportId} typ={Typ} user={User}", reportid, Form("typ"), UserAccountID);
|
||||
byte[]? content = null;
|
||||
var file = _mfr.GetReportDoc(ref content, reportid);
|
||||
if (file == null) return StatusCode(404, new { error = "Dokument wurde nicht gefunden" });
|
||||
if (file == null)
|
||||
{
|
||||
_logger.LogWarning("HandleReportDoc: document not found reportid={ReportId} user={User}", reportid, UserAccountID);
|
||||
return StatusCode(404, new { error = "Dokument wurde nicht gefunden" });
|
||||
}
|
||||
_logger.LogDebug("HandleReportDoc found reportid={ReportId} fileName={FileName} mimeType={MimeType} size={Size} user={User}",
|
||||
reportid, file.Name, file.MimeType(), content?.Length ?? 0, UserAccountID);
|
||||
return Form("typ") != "img"
|
||||
? await FileContentResultAsync(content!, file.MimeType(), file.Name)
|
||||
: await JSONAsync(new { id = reportid, img = await BuildPdfImageArray(content!) });
|
||||
@@ -225,46 +293,76 @@ public partial class IntranetController
|
||||
|
||||
private async Task<IActionResult> HandleReportDocByName(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("name")) return BadRequest400();
|
||||
if (!HasForm("name")) { _logger.LogWarning("HandleReportDocByName: missing 'name' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string nme = Form("name").LeftToFirst("(").Trim();
|
||||
if (string.IsNullOrEmpty(nme)) return StatusCode(404);
|
||||
_logger.LogDebug("HandleReportDocByName name='{Name}' user={User}", nme, UserAccountID);
|
||||
if (string.IsNullOrEmpty(nme))
|
||||
{
|
||||
_logger.LogWarning("HandleReportDocByName: empty name after trim user={User}", UserAccountID);
|
||||
return StatusCode(404);
|
||||
}
|
||||
var so = await getSQLValue_async(
|
||||
"SELECT [dbo].[fds__fn_InvoiceIdByName](@nme);",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@nme", nme)),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
string reportid = so.Result?.ToString() ?? "";
|
||||
return string.IsNullOrEmpty(reportid)
|
||||
? StatusCode(404)
|
||||
: await HandleReportDoc(fn, id, code, reportid);
|
||||
if (string.IsNullOrEmpty(reportid))
|
||||
{
|
||||
_logger.LogWarning("HandleReportDocByName: no invoice found for name='{Name}' user={User}", nme, UserAccountID);
|
||||
return StatusCode(404);
|
||||
}
|
||||
_logger.LogDebug("HandleReportDocByName resolved name='{Name}' to reportid={ReportId} user={User}", nme, reportid, UserAccountID);
|
||||
return await HandleReportDoc(fn, id, code, reportid);
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleDatevZip(string fn, string id, string code)
|
||||
{
|
||||
if (!DateTime.TryParseExact(Form("tgt"), "yy-MM-dd",
|
||||
CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var tgtdate))
|
||||
{
|
||||
_logger.LogWarning("HandleDatevZip: invalid date format tgt='{Tgt}' user={User}", Form("tgt"), UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
string mode = Form("mode").ne("m");
|
||||
bool includeFiles = Form("files", "1") != "0";
|
||||
_logger.LogDebug("HandleDatevZip tgtdate={TgtDate} mode={Mode} includeFiles={IncludeFiles} user={User}",
|
||||
tgtdate.ToString("yy-MM-dd"), mode, includeFiles, UserAccountID);
|
||||
Stream? ms = new MemoryStream();
|
||||
var file = _mfr.GetDatevZip(ref ms, tgtdate,
|
||||
mode: Form("mode").ne("m"),
|
||||
mode: mode,
|
||||
authUser: UserAccountID,
|
||||
includeFiles: Form("files", "1") != "0");
|
||||
if (file == null) return BadRequest400();
|
||||
includeFiles: includeFiles);
|
||||
if (file == null)
|
||||
{
|
||||
_logger.LogWarning("HandleDatevZip: zip generation returned null for tgtdate={TgtDate} mode={Mode} user={User}",
|
||||
tgtdate.ToString("yy-MM-dd"), mode, UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
_logger.LogInformation("HandleDatevZip sending file='{FileName}' tgtdate={TgtDate} user={User}",
|
||||
file.Name, tgtdate.ToString("yy-MM-dd"), UserAccountID);
|
||||
ms!.Position = 0;
|
||||
return await FileStreamResultAsync(ms, file.MimeType(), file.Name);
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleGetReminder(string fn, string id, string code)
|
||||
{
|
||||
if (!HasForm("id")) return BadRequest400();
|
||||
if (!HasForm("id")) { _logger.LogWarning("HandleGetReminder: missing 'id' form field user={User}", UserAccountID); return BadRequest400(); }
|
||||
string invoiceId = Form("id");
|
||||
string includeDrafts = Form("drafts");
|
||||
_logger.LogDebug("HandleGetReminder invoiceId={InvoiceId} includeDrafts={IncludeDrafts} user={User}",
|
||||
invoiceId, includeDrafts, UserAccountID);
|
||||
var pl = StdParamlist(
|
||||
SQL_VarChar("@InvId", Form("id")),
|
||||
SQL_Bit("@include_drafts", Form("drafts")));
|
||||
SQL_VarChar("@InvId", invoiceId),
|
||||
SQL_Bit("@include_drafts", includeDrafts));
|
||||
var sqldt = await getSQLDataSet_async(
|
||||
"EXECUTE [dbo].[fds__getInvoiceReminder] @InvId, @include_drafts, @authuser;",
|
||||
_intranet.Intranet__SQLConnectionString, pl,
|
||||
tablenames: new[] { "reminder" },
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
int reminderCount = sqldt.Table("reminder").DataTable.Rows.Count;
|
||||
_logger.LogDebug("HandleGetReminder invoiceId={InvoiceId} reminderCount={ReminderCount} user={User}",
|
||||
invoiceId, reminderCount, UserAccountID);
|
||||
return await JSONAsync(sqldt.Table("reminder").DataTable.toArrayofObjectDictionaries());
|
||||
}
|
||||
|
||||
|
||||
@@ -76,23 +76,27 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
|
||||
// ── Index (GET /) ─────────────────────────────────────────────────────────
|
||||
[AllowAnonymous]
|
||||
public IActionResult Index(string? fn, string? id, string? code) =>
|
||||
public IActionResult Index([FromRoute] string? fn, [FromRoute] string? id, [FromRoute] string? code) =>
|
||||
View("intranet");
|
||||
|
||||
// ── Do (POST+GET /do/{fn}/{id}/{code}) ─────────────────────────────────
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> Do(string? fn, string? id, string? code)
|
||||
public async Task<IActionResult> Do([FromRoute] string? fn, [FromRoute] string? id, [FromRoute] string? code)
|
||||
{
|
||||
fn = (fn ?? "").ToLower();
|
||||
id ??= "";
|
||||
code ??= "";
|
||||
bool isGet = HttpContext.Request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
_logger.LogDebug("Do dispatching {Fn}/{Id}/{Code} [{Method}] user={User}",
|
||||
fn, id, code, HttpContext.Request.Method, UserAccountID);
|
||||
|
||||
if (!UserIdent.IsAuthenticated && !(new string[] { "login","logout" }).Contains(fn.ToLower()) && !_allowedNonAuth.Contains(fn.ToLower()))
|
||||
{
|
||||
if (!_allowedGet.Contains(fn.ToLower()) && !_allowedGet.Contains($"{fn.ToLower()}|{id.ToLower()}"))
|
||||
{
|
||||
_logger.LogInformation($"rejected function on do {fn}");
|
||||
_logger.LogWarning("Rejected unauthenticated request for fn={Fn} id={Id} ip={IP}",
|
||||
fn, id, HttpContext.Connection.RemoteIpAddress);
|
||||
return Unauthorized401();
|
||||
}
|
||||
}
|
||||
@@ -121,12 +125,16 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
"logout" => await HandleLogout(),
|
||||
_ => null
|
||||
};
|
||||
if (result == null)
|
||||
_logger.LogWarning("No handler matched fn={Fn}", fn);
|
||||
else
|
||||
_logger.LogDebug("Do completed fn={Fn}/{Id} result={ResultType}", fn, id, result.GetType().Name);
|
||||
return result ?? Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_intranet.debug_log("IntranetController.Do", ex, UserAccountID,
|
||||
data: new { fn, id, code });
|
||||
_logger.LogError(ex, "Unhandled exception in Do fn={Fn} id={Id} code={Code} user={User}",
|
||||
fn, id, code, UserAccountID);
|
||||
return ServerError();
|
||||
}
|
||||
}
|
||||
@@ -134,8 +142,14 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
// ── Auth helper ───────────────────────────────────────────────────────────
|
||||
private async Task<IActionResult> HandleAuth(string fn, string id, string code)
|
||||
{
|
||||
if (!Request.Form.ContainsKey("module")) return BadRequest400();
|
||||
if (!Request.Form.ContainsKey("module"))
|
||||
{
|
||||
_logger.LogWarning("HandleAuth called without 'module' form field by user={User}", UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
string module = Request.Form["module"].ToString();
|
||||
_logger.LogDebug("HandleAuth module={Module} array={Array} user={User}",
|
||||
module, Request.Form["array"].ToString(), UserAccountID);
|
||||
if (Request.Form["array"] == "1")
|
||||
{
|
||||
var dt = await getSQLDatatable_async(
|
||||
@@ -143,6 +157,8 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
StdParamlist(SQL_VarChar("@module", module)),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
_logger.LogDebug("HandleAuth returned {Count} module auth entries for user={User}",
|
||||
dt.DataTable.Rows.Count, UserAccountID);
|
||||
return await JSONAsync(dt.DataTable.ToDictionary(KeyColumn: "module", ValueColumn: "auth"));
|
||||
}
|
||||
else
|
||||
@@ -152,6 +168,8 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
_intranet.Intranet__SQLConnectionString, -1,
|
||||
StdParamlist(SQL_VarChar("@module", module)),
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
_logger.LogDebug("HandleAuth module={Module} auth={Auth} user={User}",
|
||||
module, val.Result, UserAccountID);
|
||||
return await JSONAsync(new { auth = val.Result });
|
||||
}
|
||||
}
|
||||
@@ -162,13 +180,13 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
{
|
||||
string email = Request.Form["userinfo"].ToString();
|
||||
string password = Request.Form["userpass"].ToString();
|
||||
_logger.LogDebug("HandleLogin attempt for email={Email} ip={IP}",
|
||||
email, HttpContext.Connection.RemoteIpAddress);
|
||||
var row = await _intranet.AuthenticateAsync(email, password);
|
||||
if (row == null)
|
||||
{
|
||||
_logger.LogWarning("Login failed for '{Email}' from {IP}",
|
||||
_logger.LogWarning("Login failed for email={Email} ip={IP}",
|
||||
email, HttpContext.Connection.RemoteIpAddress);
|
||||
_intranet.debug_log("HandleLogin: failed",
|
||||
data: new { email, ip = HttpContext.Connection.RemoteIpAddress?.ToString() });
|
||||
return Unauthorized401();
|
||||
}
|
||||
|
||||
@@ -179,6 +197,8 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
var identity = FuchsUserIdentity.BuildIdentity(userId, userEmail, auth, Fuchs_intranet.AuthScheme);
|
||||
var principal = new System.Security.Claims.ClaimsPrincipal(identity);
|
||||
await HttpContext.SignInAsync(Fuchs_intranet.AuthScheme, principal);
|
||||
_logger.LogInformation("Login succeeded for userId={UserId} email={Email} authorization={Auth} ip={IP}",
|
||||
userId, userEmail, auth, HttpContext.Connection.RemoteIpAddress);
|
||||
return await JSONAsync(new
|
||||
{
|
||||
login = userEmail,
|
||||
@@ -192,7 +212,10 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
|
||||
private async Task<IActionResult> HandleLogout()
|
||||
{
|
||||
_logger.LogInformation("Logout user={User} ip={IP}",
|
||||
UserAccountID, HttpContext.Connection.RemoteIpAddress);
|
||||
await HttpContext.SignOutAsync(Fuchs_intranet.AuthScheme);
|
||||
_logger.LogDebug("Logout sign-out complete for user={User}", UserAccountID);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
@@ -201,16 +224,27 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
{
|
||||
string? lastname = Request.Form["lastname"];
|
||||
string? email = Request.Form["email"];
|
||||
if (string.IsNullOrEmpty(lastname) || string.IsNullOrEmpty(email)) return BadRequest400();
|
||||
_logger.LogDebug("HandleSendPasswordCode called for email={Email}", email);
|
||||
if (string.IsNullOrEmpty(lastname) || string.IsNullOrEmpty(email))
|
||||
{
|
||||
_logger.LogWarning("HandleSendPasswordCode missing lastname or email");
|
||||
return BadRequest400();
|
||||
}
|
||||
|
||||
var row = await _intranet.GetUserAccountByEmailAsync(email);
|
||||
if (row != null && row.nz("email").Length > 5 &&
|
||||
row.nz("name").ToLower().Trim() == lastname.ToLower().Trim() &&
|
||||
row.nz("mobile").Length > 5 && !Request.Host.Host.ToLower().Contains("localhost"))
|
||||
{
|
||||
_logger.LogInformation("Sending password code SMS to mobile for email={Email}", email);
|
||||
string totp = OCORE.security.TFA.generateTotp_12h(_intranet.Intranet__TOTPsharedsecret_base);
|
||||
await _comService.SendSmsAsync(row.nz("mobile"),
|
||||
"Zur Bestätigung des Passwortversands auf sanitarfuchs.de, verwenden Sie bitte folgenden Code:" + totp);
|
||||
_logger.LogDebug("Password code SMS sent for email={Email}", email);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("HandleSendPasswordCode: no SMS sent for email={Email} (user not found, name mismatch, no mobile, or localhost)", email);
|
||||
}
|
||||
return Ok(); // always OK to prevent enumeration
|
||||
}
|
||||
@@ -220,34 +254,57 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
string? lastname = Request.Form["lastname"];
|
||||
string? email = Request.Form["email"];
|
||||
string? totpCode = Request.Form["code"];
|
||||
_logger.LogDebug("HandleSendPassword called for email={Email}", email);
|
||||
if (string.IsNullOrEmpty(lastname) || string.IsNullOrEmpty(email) || string.IsNullOrEmpty(totpCode))
|
||||
return BadRequest400();
|
||||
|
||||
if (OCORE.security.TFA.validateTotp_12h(_intranet.Intranet__TOTPsharedsecret_base, totpCode).isVerifiedInTime)
|
||||
{
|
||||
_logger.LogWarning("HandleSendPassword missing required fields (lastname, email or code)");
|
||||
return BadRequest400();
|
||||
}
|
||||
|
||||
var totpResult = OCORE.security.TFA.validateTotp_12h(_intranet.Intranet__TOTPsharedsecret_base, totpCode);
|
||||
if (totpResult.isVerifiedInTime)
|
||||
{
|
||||
_logger.LogDebug("HandleSendPassword TOTP verified for email={Email}", email);
|
||||
var row = await _intranet.GetUserAccountByEmailAsync(email, includePassword: true);
|
||||
if (row != null && row.nz("email").Length > 5)
|
||||
{
|
||||
_logger.LogInformation("Sending password email to email={Email}", email);
|
||||
await _comService.SendEmailAsync("pw_" + row.nz("email"),
|
||||
"sanitaerfuchs.de Intranet Passwort",
|
||||
$"<p>Guten Tag {row.nz("firstname")} {row.nz("name")},<br/>Ihr Passwort: {HttpUtility.HtmlEncode(row.nz("password"))}</p>",
|
||||
row.nz("email"), $"{row.nz("firstname")} {row.nz("name")}", null);
|
||||
_logger.LogDebug("Password email sent for email={Email}", email);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("HandleSendPassword: user not found for email={Email}", email);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("HandleSendPassword: TOTP verification failed for email={Email}", email);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleAccount(string fn, string id, string code)
|
||||
{
|
||||
_logger.LogDebug("HandleAccount action={Action} user={User}", id, UserAccountID);
|
||||
switch (id.ToLower())
|
||||
{
|
||||
case "sms":
|
||||
var row = await _intranet.GetUserAccountByEmailAsync(UserIdent.Email, includePassword: true);
|
||||
if (row != null && row.nz("mobile").Length > 5 && !Request.Host.Host.Contains("localhost"))
|
||||
{
|
||||
_logger.LogInformation("Sending change-password confirmation SMS to user={User}", UserAccountID);
|
||||
string totp2 = OCORE.security.TFA.generateTotp_3h(_intranet.Intranet__TOTPsharedsecret_base + "3MDR");
|
||||
await _comService.SendSmsAsync(row.nz("mobile"),
|
||||
"Zur Bestätigung der Passwortänderung auf sanitarfuchs.de: " + totp2);
|
||||
_logger.LogDebug("Change-password SMS sent for user={User}", UserAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("HandleAccount sms: no SMS sent for user={User} (no mobile or localhost)", UserAccountID);
|
||||
}
|
||||
return Ok();
|
||||
|
||||
@@ -256,9 +313,16 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
string? npwc = Request.Form["npwc"];
|
||||
string? totpCode = Request.Form["code"];
|
||||
if (string.IsNullOrEmpty(npw) || string.IsNullOrEmpty(npwc) || string.IsNullOrEmpty(totpCode))
|
||||
{
|
||||
_logger.LogWarning("HandleAccount changepassword: missing required fields for user={User}", UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
if (!OCORE.security.TFA.validateTotp_3h(_intranet.Intranet__TOTPsharedsecret_base + "3MDR", totpCode).isVerifiedInTime)
|
||||
{
|
||||
_logger.LogWarning("HandleAccount changepassword: TOTP verification failed for user={User}", UserAccountID);
|
||||
return StatusCode(409, new { error = "sms" });
|
||||
}
|
||||
_logger.LogInformation("Changing password for user={User}", UserAccountID);
|
||||
await setSQLValue_async(
|
||||
"EXECUTE [dbo].[fis_admin_setNewPassword] @useraccount_id, @oldpassword, @newpassword, @enc_key;",
|
||||
_intranet.Intranet__SQLConnectionString,
|
||||
@@ -269,39 +333,55 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
|
||||
SQL_VarChar("@newpassword", npw)
|
||||
},
|
||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||
_logger.LogDebug("Password changed successfully for user={User}", UserAccountID);
|
||||
return Ok();
|
||||
}
|
||||
_logger.LogWarning("HandleAccount unknown action={Action} user={User}", id, UserAccountID);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleMfr(string fn, string id, string code)
|
||||
{
|
||||
_logger.LogDebug("HandleMfr id={Id} code={Code} user={User} auth={Auth}",
|
||||
id, code, UserAccountID, UserIdent.Authorization);
|
||||
if (!string.IsNullOrEmpty(UserAccountID) && UserIdent.Authorization > 3)
|
||||
{
|
||||
string path = id + (!string.IsNullOrEmpty(code) ? "/" + code : HttpUtility.UrlDecode(Request.QueryString.Value ?? ""));
|
||||
_logger.LogDebug("HandleMfr reading OData path={Path} user={User}", path, UserAccountID);
|
||||
using var mfrRead = new fds.FdsMfrClient();
|
||||
var result = await mfrRead.ReadOData(path, throwErrorIfNotOk: false);
|
||||
_logger.LogDebug("HandleMfr OData read complete for path={Path} user={User}", path, UserAccountID);
|
||||
return Content(JsonConvert.SerializeObject(result), "application/json");
|
||||
}
|
||||
_logger.LogWarning("HandleMfr access denied for user={User} authorization={Auth}",
|
||||
UserAccountID, UserIdent.Authorization);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
private async Task<IActionResult> HandleMfrUpdate(string fn, string id, string code)
|
||||
{
|
||||
var et = EntityHelper.EntityValue(Request.Form["type"].ToString());
|
||||
string typeParam = Request.Form["type"].ToString();
|
||||
string needParam = Request.Form["need"].ToString();
|
||||
var et = EntityHelper.EntityValue(typeParam);
|
||||
_logger.LogDebug("HandleMfrUpdate type={Type} need={Need} user={User}", typeParam, needParam, UserAccountID);
|
||||
if (et != EntityTypes.none && string.IsNullOrEmpty(Request.Form["need"]))
|
||||
{
|
||||
_logger.LogInformation("MfrUpdate entity={EntityType} need=Short user={User}", et, UserAccountID);
|
||||
using var mfrSingle = new fds.FdsMfrClient();
|
||||
await mfrSingle.Update__entitytable(et, fds.FdsMfr.UpdateNeed.Short);
|
||||
_logger.LogDebug("MfrUpdate Short completed for entity={EntityType}", et);
|
||||
return Ok();
|
||||
}
|
||||
if (et != EntityTypes.none && !string.IsNullOrEmpty(Request.Form["need"]))
|
||||
{
|
||||
var need = fds.FdsMfr.UpdateNeedValue(Request.Form["need"].ToString());
|
||||
var need = fds.FdsMfr.UpdateNeedValue(needParam);
|
||||
_logger.LogInformation("MfrUpdate entity={EntityType} need={Need} user={User}", et, need, UserAccountID);
|
||||
using var mfr = new fds.FdsMfrClient();
|
||||
await mfr.Update__entitytable(et, updateNeed: need, debugDetails: false);
|
||||
_logger.LogDebug("MfrUpdate completed for entity={EntityType} need={Need}", et, need);
|
||||
return Ok();
|
||||
}
|
||||
_logger.LogWarning("HandleMfrUpdate bad request: unknown type={Type} user={User}", typeParam, UserAccountID);
|
||||
return BadRequest400();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ function getMonday(d) {
|
||||
$.fn.rwText = function (text, addtitle, options) {
|
||||
var tgt = $(this).empty();
|
||||
options = $.extend({ wrap: true }, options);
|
||||
var sa = Array.isArray(text) === true ? text : (text || '').split('\n');
|
||||
var sa = Array.isArray(text) === true ? text : (text == null ? '' : String(text)).split('\n');
|
||||
$.each(sa, function (ti, tx) {
|
||||
if ((tx || '') !== '') {
|
||||
if (ti > 0) {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1317,7 +1317,7 @@ function getMonday(d) {
|
||||
$.fn.rwText = function (text, addtitle, options) {
|
||||
var tgt = $(this).empty();
|
||||
options = $.extend({ wrap: true }, options);
|
||||
var sa = Array.isArray(text) === true ? text : (text || '').split('\n');
|
||||
var sa = Array.isArray(text) === true ? text : (text == null ? '' : String(text)).split('\n');
|
||||
$.each(sa, function (ti, tx) {
|
||||
if ((tx || '') !== '') {
|
||||
if (ti > 0) {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
Submodule OCORE updated: 758c28e934...3cf8cd1dd5
Reference in New Issue
Block a user