summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2024-03-22 12:28:07 +0000
committerIan C <ianc@noddybox.co.uk>2024-03-22 12:28:07 +0000
commit3f05ee34d209fcb994cba50955cd2e301315d9bd (patch)
tree5cd375c2e8ecc444786286af4d1afcbcaf95227e
parentd71f080ad276653399c92810c9122bf537e551fe (diff)
Initial working version.
-rw-r--r--Download.cs17
-rw-r--r--Pages/Index.cshtml79
-rw-r--r--Pages/Index.cshtml.cs114
-rw-r--r--Pages/Privacy.cshtml8
-rw-r--r--Pages/Privacy.cshtml.cs19
-rw-r--r--Pages/Report.cshtml43
-rw-r--r--Pages/Report.cshtml.cs111
-rw-r--r--Pages/Shared/_Layout.cshtml13
8 files changed, 320 insertions, 84 deletions
diff --git a/Download.cs b/Download.cs
new file mode 100644
index 0000000..6e043cb
--- /dev/null
+++ b/Download.cs
@@ -0,0 +1,17 @@
+namespace download_admin;
+
+public class Download
+{
+ public string Key {get; private set;}
+ public string IpAddress {get; private set;}
+ public string UserAgent {get; private set;}
+ public DateTime Time {get; private set;}
+
+ public Download(string key, string ip_address, string user_agent, DateTime time)
+ {
+ Key = key;
+ IpAddress = ip_address;
+ UserAgent = user_agent;
+ Time = time;
+ }
+}
diff --git a/Pages/Index.cshtml b/Pages/Index.cshtml
index 9c1f3c2..469011c 100644
--- a/Pages/Index.cshtml
+++ b/Pages/Index.cshtml
@@ -1,48 +1,37 @@
@page
@model download_admin.Pages.IndexModel
@using download_admin.Pages
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Download Repsoitory Editor</title>
- </head>
- <body>
- <a href="report">Download Report</a><br>
- @if (Model.HasError)
- {
- <p style="color:red"><b>@Model.ErrorText</b></p>
- }
- <table>
- <tr>
- <td style="width:25%;"><b>Key</b></td>
- <td style="width:20%;"><b>Mime type</b></td>
- <td style="width:20%;"><b>File name</b></td>
- <td style="width:15%;"><b>File data</b></td>
- <td style="width:20%;"><b>Commands</b></td>
- </tr>
- @foreach(FileObject obj in Model.Rows)
- {
- <tr>
- <form enctype="multipart/form-data" method="post">
- <td><input type=text name="Key" maxlength=64 value="@obj.Key"></td>
- <td><input type=text name="MimeType" maxlength=64 value="@obj.MimeType"></td>
- <td><input type=text name="Filename" maxlength=64 value="@obj.FileName"></td>
- <td><input type=file name="Data"></td>
- <td><input type="submit" name="update" value="Update"><input type="submit" name="delete" value="Delete"></td>
- </form>
- </tr>
- }
- <tr>
- <form enctype="multipart/form-data" method="post">
- <td><input type=text name="Key" maxlength=64 value=""></td>
- <td><input type=text name="MimeType" maxlength=64 value=""></td>
- <td><input type=text name="Filename" maxlength=64 value=""></td>
- <td><input type=file name="Data"></td>
- <td><input type="submit" name="add" value="Add"></td>
- </form>
- </tr>
- </table>
- </body>
-</html>
+@if (Model.HasError)
+{
+ <p style="color:red"><b>@Model.ErrorText</b></p>
+}
+<table>
+ <tr>
+ <td style="width:25%;"><b>Key</b></td>
+ <td style="width:20%;"><b>Mime type</b></td>
+ <td style="width:20%;"><b>File name</b></td>
+ <td style="width:15%;"><b>File data</b></td>
+ <td style="width:20%;"><b>Commands</b></td>
+ </tr>
+ @foreach(FileObject obj in Model.Rows)
+ {
+ <tr>
+ <form enctype="multipart/form-data" method="post">
+ <td><input type=text name="key" maxlength=64 value="@obj.Key"></td>
+ <td><input type=text name="mime_type" maxlength=64 value="@obj.MimeType"></td>
+ <td><input type=text name="file_name" maxlength=64 value="@obj.FileName"></td>
+ <td><input type=file name="file"></td>
+ <td><input type="submit" name="update" value="Update"><input type="submit" name="delete" value="Delete"><input readonly style="display: none" type=text name="original_key" maxlength=64 value="@obj.Key"></td>
+ </form>
+ </tr>
+ }
+ <tr>
+ <form enctype="multipart/form-data" method="post">
+ <td><input type=text name="key" maxlength=64 value=""></td>
+ <td><input type=text name="mime_type" maxlength=64 value=""></td>
+ <td><input type=text name="file_name" maxlength=64 value=""></td>
+ <td><input type=file name="file"></td>
+ <td><input type="submit" name="add" value="Add"></td>
+ </form>
+ </tr>
+</table> \ No newline at end of file
diff --git a/Pages/Index.cshtml.cs b/Pages/Index.cshtml.cs
index 6e9a5ed..90c18db 100644
--- a/Pages/Index.cshtml.cs
+++ b/Pages/Index.cshtml.cs
@@ -17,11 +17,14 @@ public class IndexModel : PageModel
public void OnGet()
{
+ ViewData["Title"] = "Download Repsoitory Editor";
LoadData();
}
public void OnPost()
{
+ ViewData["Title"] = "Download Repsoitory Editor";
+
if (!String.IsNullOrEmpty(Request.Form["add"]))
{
DoAdd();
@@ -47,17 +50,122 @@ public class IndexModel : PageModel
private void DoAdd()
{
- SetError("DoAdd");
+ try
+ {
+ string? key = Request.Form["key"];
+ string? mime_type = Request.Form["mime_type"];
+ string? file_name = Request.Form["file_name"];
+ IFormFile? file = Request.Form.Files.Count > 0 ? Request.Form.Files[0] : null;
+
+ if (String.IsNullOrWhiteSpace(key) ||
+ String.IsNullOrWhiteSpace(mime_type) ||
+ String.IsNullOrEmpty(file_name) ||
+ file == null)
+ {
+ SetError("Need key, mime type, file name and file");
+ return;
+ }
+
+ using var file_stream = file.OpenReadStream();
+ byte[] file_data = new byte[file.Length];
+ file_stream.Read(file_data, 0, (int)file.Length);
+
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var cmd = new NpgsqlCommand("INSERT INTO file_object (key, mime_type, file_name, data) VALUES (@key, @mime_type, @file_name, @data)", conn);
+
+ cmd.Parameters.AddWithValue("key", NpgsqlTypes.NpgsqlDbType.Varchar, key);
+ cmd.Parameters.AddWithValue("mime_type", NpgsqlTypes.NpgsqlDbType.Varchar, mime_type);
+ cmd.Parameters.AddWithValue("file_name", NpgsqlTypes.NpgsqlDbType.Varchar, file_name);
+ cmd.Parameters.AddWithValue("data", NpgsqlTypes.NpgsqlDbType.Bytea, file_data);
+
+ cmd.ExecuteNonQuery();
+ }
+ catch(Exception e)
+ {
+ SetError(e.Message);
+ }
}
private void DoDelete()
{
- SetError("DoDelete");
+ try
+ {
+ string? key = Request.Form["original_key"];
+
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var delete_download = new NpgsqlCommand("DELETE FROM download WHERE key = @original_key", conn);
+
+ delete_download.Parameters.AddWithValue("original_key", NpgsqlTypes.NpgsqlDbType.Varchar, key);
+ delete_download.ExecuteNonQuery();
+
+ using var delete_file = new NpgsqlCommand("DELETE FROM file_object WHERE key = @original_key", conn);
+
+ delete_file.Parameters.AddWithValue("original_key", NpgsqlTypes.NpgsqlDbType.Varchar, key);
+ delete_file.ExecuteNonQuery();
+ }
+ catch(Exception e)
+ {
+ SetError(e.Message);
+ }
}
private void DoUpdate()
{
- SetError("DoUpdate");
+ try
+ {
+ string? original_key = Request.Form["original_key"];
+ string? key = Request.Form["key"];
+ string? mime_type = Request.Form["mime_type"];
+ string? file_name = Request.Form["file_name"];
+ IFormFile? file = Request.Form.Files.Count > 0 ? Request.Form.Files[0] : null;
+
+ if (file != null)
+ {
+ using var file_stream = file.OpenReadStream();
+ byte[] file_data = new byte[file.Length];
+ file_stream.Read(file_data, 0, (int)file.Length);
+
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var cmd = new NpgsqlCommand("UPDATE file_object set key=@key, mime_type=@mime_type, file_name=@file_name, data=@data WHERE key=@original_key", conn);
+
+ cmd.Parameters.AddWithValue("original_key", NpgsqlTypes.NpgsqlDbType.Varchar, original_key);
+ cmd.Parameters.AddWithValue("key", NpgsqlTypes.NpgsqlDbType.Varchar, key);
+ cmd.Parameters.AddWithValue("mime_type", NpgsqlTypes.NpgsqlDbType.Varchar, mime_type);
+ cmd.Parameters.AddWithValue("file_name", NpgsqlTypes.NpgsqlDbType.Varchar, file_name);
+ cmd.Parameters.AddWithValue("data", NpgsqlTypes.NpgsqlDbType.Bytea, file_data);
+
+ cmd.ExecuteNonQuery();
+ }
+ else
+ {
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var cmd = new NpgsqlCommand("UPDATE file_object set key=@key, mime_type=@mime_type, file_name=@file_name WHERE key=@original_key", conn);
+
+ cmd.Parameters.AddWithValue("original_key", NpgsqlTypes.NpgsqlDbType.Varchar, original_key);
+ cmd.Parameters.AddWithValue("key", NpgsqlTypes.NpgsqlDbType.Varchar, key);
+ cmd.Parameters.AddWithValue("mime_type", NpgsqlTypes.NpgsqlDbType.Varchar, mime_type);
+ cmd.Parameters.AddWithValue("file_name", NpgsqlTypes.NpgsqlDbType.Varchar, file_name);
+
+ cmd.ExecuteNonQuery();
+ }
+
+ }
+ catch(Exception e)
+ {
+ SetError(e.Message);
+ }
}
private void LoadData()
diff --git a/Pages/Privacy.cshtml b/Pages/Privacy.cshtml
deleted file mode 100644
index 46ba966..0000000
--- a/Pages/Privacy.cshtml
+++ /dev/null
@@ -1,8 +0,0 @@
-@page
-@model PrivacyModel
-@{
- ViewData["Title"] = "Privacy Policy";
-}
-<h1>@ViewData["Title"]</h1>
-
-<p>Use this page to detail your site's privacy policy.</p>
diff --git a/Pages/Privacy.cshtml.cs b/Pages/Privacy.cshtml.cs
deleted file mode 100644
index 9afceae..0000000
--- a/Pages/Privacy.cshtml.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
-
-namespace download_admin.Pages;
-
-public class PrivacyModel : PageModel
-{
- private readonly ILogger<PrivacyModel> _logger;
-
- public PrivacyModel(ILogger<PrivacyModel> logger)
- {
- _logger = logger;
- }
-
- public void OnGet()
- {
- }
-}
-
diff --git a/Pages/Report.cshtml b/Pages/Report.cshtml
new file mode 100644
index 0000000..b928ef5
--- /dev/null
+++ b/Pages/Report.cshtml
@@ -0,0 +1,43 @@
+@page
+@model download_admin.Pages.ReportModel
+
+@if (Model.HasError)
+{
+ <p style="color:red"><b>@Model.ErrorText</b></p>
+}
+<h1>Count for each key</h1>
+
+<table>
+ <tr>
+ <td style="width:50%;"><b>Key</b></td>
+ <td style="width:50%;"><b>Downloads</b></td>
+ </tr>
+
+ @foreach (string t in Model.Keys)
+ {
+ <tr>
+ <td>@t</td>
+ <td>@Model.GetCount(t)</td>
+ </tr>
+ }
+</table>
+
+<h1>Download Details</h1>
+
+<table>
+ <tr>
+ <td style="width:25%;"><b>Time</b></td>
+ <td style="width:25%;"><b>Key</b></td>
+ <td style="width:25%;"><b>IP Address</b></td>
+ <td style="width:25%;"><b>User Agent</b></td>
+ </tr>
+ @foreach(Download obj in Model.Rows)
+ {
+ <tr>
+ <td>@obj.Time</td>
+ <td>@obj.Key</td>
+ <td>@obj.IpAddress</td>
+ <td>@obj.UserAgent</td>
+ </tr>
+ }
+</table> \ No newline at end of file
diff --git a/Pages/Report.cshtml.cs b/Pages/Report.cshtml.cs
new file mode 100644
index 0000000..37e2c11
--- /dev/null
+++ b/Pages/Report.cshtml.cs
@@ -0,0 +1,111 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Npgsql;
+using System.Collections.Generic;
+using download_admin;
+
+namespace download_admin.Pages;
+
+public class ReportModel : PageModel
+{
+ public void OnGet()
+ {
+ ViewData["Title"] = "Download Repsoitory Report";
+
+ try
+ {
+ Rows = new List<Download>();
+
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var cmd = new NpgsqlCommand("SELECT key, ip_address, user_agent, time FROM download ORDER BY time", conn);
+ using var reader = cmd.ExecuteReader();
+
+ while(reader.Read())
+ {
+ string key = (string)reader["key"];
+ string ip_address = (string)reader["ip_address"];
+ string user_agent = (string)reader["user_agent"];
+ DateTime time = (DateTime)reader["time"];
+
+ Rows.Add(new Download(key, ip_address, user_agent, time));
+ }
+ }
+ catch(Exception e)
+ {
+ SetError(e.Message);
+ }
+ }
+
+ private void SetError(string error_text)
+ {
+ HasError = true;
+ ErrorText = error_text;
+ }
+
+ public List<string> Keys
+ {
+ get
+ {
+ var keys = new List<String>();
+
+ try
+ {
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var cmd = new NpgsqlCommand("SELECT key FROM file_object ORDER BY key", conn);
+ using var reader = cmd.ExecuteReader();
+
+ while(reader.Read())
+ {
+ string key = (string)reader["key"];
+ keys.Add(key);
+ }
+ }
+ catch(Exception e)
+ {
+ SetError(e.Message);
+ }
+
+ return keys;
+ }
+
+ }
+
+ public long GetCount(string key)
+ {
+ try
+ {
+ using var conn = new NpgsqlConnection(Config.Settings["ConnectionStrings:download"]);
+
+ conn.Open();
+
+ using var cmd = new NpgsqlCommand("SELECT count(*) FROM download where key = @key", conn);
+ cmd.Parameters.AddWithValue("key", NpgsqlTypes.NpgsqlDbType.Varchar, key);
+
+ object? scalar = cmd.ExecuteScalar();
+
+ if (scalar != null)
+ {
+ return (long)scalar;
+ }
+ }
+ catch(Exception e)
+ {
+ SetError(e.Message);
+ }
+
+ return 0;
+ }
+
+ public List<Download>? Rows {get;private set;}
+
+ public bool HasError {get; private set;}
+
+ public string? ErrorText {get; private set;}
+
+}
diff --git a/Pages/Shared/_Layout.cshtml b/Pages/Shared/_Layout.cshtml
index 86c0cc1..cc18cc7 100644
--- a/Pages/Shared/_Layout.cshtml
+++ b/Pages/Shared/_Layout.cshtml
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>@ViewData["Title"] - download_admin</title>
+ <title>@ViewData["Title"]</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/download_admin.styles.css" asp-append-version="true" />
@@ -20,10 +20,10 @@
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" asp-area="" asp-page="/Index">Download Repository Editor</a>
</li>
<li class="nav-item">
- <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
+ <a class="nav-link text-dark" asp-area="" asp-page="/Report">Download Repository Report</a>
</li>
</ul>
</div>
@@ -38,14 +38,9 @@
<footer class="border-top footer text-muted">
<div class="container">
- &copy; 2024 - download_admin - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ &copy; 2024 - <a href="http://deathstation9000.org.uk">download_admin</a>
</div>
</footer>
- <script src="~/lib/jquery/dist/jquery.min.js"></script>
- <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
- <script src="~/js/site.js" asp-append-version="true"></script>
-
- @await RenderSectionAsync("Scripts", required: false)
</body>
</html> \ No newline at end of file