From 1a96616699ab41bf6343bc1acc45a836c3e6caf3 Mon Sep 17 00:00:00 2001 From: Paweł Bernaciak Date: Fri, 22 Dec 2023 16:02:41 +0100 Subject: Backup --- .idea/.idea.CoreWiki/.idea/.name | 1 + .idea/.idea.CoreWiki/.idea/efCoreCommonOptions.xml | 15 +++ .idea/.idea.CoreWiki/.idea/efCoreDialogsState.xml | 14 +++ .idea/.idea.CoreWiki/.idea/vcs.xml | 6 ++ .../Migrations/20230209093124_initial.Designer.cs | 42 --------- CoreWiki/Migrations/20230209093124_initial.cs | 35 ------- .../Migrations/20231222134125_Initial.Designer.cs | 57 +++++++++++ CoreWiki/Migrations/20231222134125_Initial.cs | 41 ++++++++ .../ApplicationDbContextModelSnapshot.cs | 21 ++++- CoreWiki/Models/ApplicationDbContext.cs | 9 +- CoreWiki/Models/Article.cs | 13 ++- CoreWiki/Pages/All.cshtml | 48 ++++++++++ CoreWiki/Pages/All.cshtml.cs | 39 ++++++++ CoreWiki/Pages/Create.cshtml | 4 +- CoreWiki/Pages/Create.cshtml.cs | 14 ++- CoreWiki/Pages/Delete.cshtml | 6 +- CoreWiki/Pages/Delete.cshtml.cs | 33 +++---- CoreWiki/Pages/Details.cshtml | 8 +- CoreWiki/Pages/Details.cshtml.cs | 23 ++--- CoreWiki/Pages/Edit.cshtml | 12 +-- CoreWiki/Pages/Edit.cshtml.cs | 17 +--- CoreWiki/Pages/LatestChanges.cshtml | 6 +- CoreWiki/Pages/Shared/_Layout.cshtml | 15 +-- CoreWiki/Program.cs | 14 +-- CoreWiki/Utils/SafeUrl.cs | 104 +++++++++++++++++++++ CoreWiki/wiki.db | Bin 20480 -> 20480 bytes CoreWiki/wiki.db-shm | Bin 32768 -> 0 bytes CoreWiki/wiki.db-wal | Bin 4152 -> 0 bytes CoreWiki/wwwroot/js/site.js | 8 +- package-lock.json | 6 ++ 30 files changed, 445 insertions(+), 166 deletions(-) create mode 100644 .idea/.idea.CoreWiki/.idea/.name create mode 100644 .idea/.idea.CoreWiki/.idea/efCoreCommonOptions.xml create mode 100644 .idea/.idea.CoreWiki/.idea/efCoreDialogsState.xml create mode 100644 .idea/.idea.CoreWiki/.idea/vcs.xml delete mode 100644 CoreWiki/Migrations/20230209093124_initial.Designer.cs delete mode 100644 CoreWiki/Migrations/20230209093124_initial.cs create mode 100644 CoreWiki/Migrations/20231222134125_Initial.Designer.cs create mode 100644 CoreWiki/Migrations/20231222134125_Initial.cs create mode 100644 CoreWiki/Pages/All.cshtml create mode 100644 CoreWiki/Pages/All.cshtml.cs create mode 100644 CoreWiki/Utils/SafeUrl.cs delete mode 100644 CoreWiki/wiki.db-shm delete mode 100644 CoreWiki/wiki.db-wal create mode 100644 package-lock.json diff --git a/.idea/.idea.CoreWiki/.idea/.name b/.idea/.idea.CoreWiki/.idea/.name new file mode 100644 index 0000000..5329c0b --- /dev/null +++ b/.idea/.idea.CoreWiki/.idea/.name @@ -0,0 +1 @@ +CoreWiki \ No newline at end of file diff --git a/.idea/.idea.CoreWiki/.idea/efCoreCommonOptions.xml b/.idea/.idea.CoreWiki/.idea/efCoreCommonOptions.xml new file mode 100644 index 0000000..a92379a --- /dev/null +++ b/.idea/.idea.CoreWiki/.idea/efCoreCommonOptions.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.CoreWiki/.idea/efCoreDialogsState.xml b/.idea/.idea.CoreWiki/.idea/efCoreDialogsState.xml new file mode 100644 index 0000000..e4d84e3 --- /dev/null +++ b/.idea/.idea.CoreWiki/.idea/efCoreDialogsState.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.CoreWiki/.idea/vcs.xml b/.idea/.idea.CoreWiki/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.CoreWiki/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CoreWiki/Migrations/20230209093124_initial.Designer.cs b/CoreWiki/Migrations/20230209093124_initial.Designer.cs deleted file mode 100644 index 11af7b7..0000000 --- a/CoreWiki/Migrations/20230209093124_initial.Designer.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -using System; -using CoreWiki.Models; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace CoreWiki.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20230209093124_initial")] - partial class initial - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); - - modelBuilder.Entity("CoreWiki.Models.Article", b => - { - b.Property("Topic") - .HasColumnType("TEXT"); - - b.Property("Content") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Published") - .HasColumnType("TEXT"); - - b.HasKey("Topic"); - - b.ToTable("Articles"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/CoreWiki/Migrations/20230209093124_initial.cs b/CoreWiki/Migrations/20230209093124_initial.cs deleted file mode 100644 index 84a7453..0000000 --- a/CoreWiki/Migrations/20230209093124_initial.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace CoreWiki.Migrations -{ - /// - public partial class initial : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Articles", - columns: table => new - { - Topic = table.Column(type: "TEXT", nullable: false), - Published = table.Column(type: "TEXT", nullable: false), - Content = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Articles", x => x.Topic); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Articles"); - } - } -} diff --git a/CoreWiki/Migrations/20231222134125_Initial.Designer.cs b/CoreWiki/Migrations/20231222134125_Initial.Designer.cs new file mode 100644 index 0000000..8c6556e --- /dev/null +++ b/CoreWiki/Migrations/20231222134125_Initial.Designer.cs @@ -0,0 +1,57 @@ +// +using System; +using CoreWiki.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CoreWiki.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20231222134125_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("CoreWiki.Models.Article", b => + { + b.Property("Slug") + .HasColumnType("TEXT"); + + b.Property("Content") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PublishedDateTime") + .HasColumnType("TEXT") + .HasColumnName("Published"); + + b.Property("Topic") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Slug"); + + b.ToTable("Articles"); + + b.HasData( + new + { + Slug = "home-page", + Content = "Welcome to your new CoreWiki installation", + PublishedDateTime = new DateTime(2023, 12, 22, 13, 41, 24, 978, DateTimeKind.Utc).AddTicks(110), + Topic = "Home Page" + }); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CoreWiki/Migrations/20231222134125_Initial.cs b/CoreWiki/Migrations/20231222134125_Initial.cs new file mode 100644 index 0000000..80c0c6e --- /dev/null +++ b/CoreWiki/Migrations/20231222134125_Initial.cs @@ -0,0 +1,41 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CoreWiki.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Articles", + columns: table => new + { + Slug = table.Column(type: "TEXT", nullable: false), + Topic = table.Column(type: "TEXT", maxLength: 100, nullable: false), + Published = table.Column(type: "TEXT", nullable: false), + Content = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Articles", x => x.Slug); + }); + + migrationBuilder.InsertData( + table: "Articles", + columns: new[] { "Slug", "Content", "Published", "Topic" }, + values: new object[] { "home-page", "Welcome to your new CoreWiki installation", new DateTime(2023, 12, 22, 13, 41, 24, 978, DateTimeKind.Utc).AddTicks(110), "Home Page" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Articles"); + } + } +} diff --git a/CoreWiki/Migrations/ApplicationDbContextModelSnapshot.cs b/CoreWiki/Migrations/ApplicationDbContextModelSnapshot.cs index fb063f5..4808c70 100644 --- a/CoreWiki/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/CoreWiki/Migrations/ApplicationDbContextModelSnapshot.cs @@ -19,19 +19,34 @@ namespace CoreWiki.Migrations modelBuilder.Entity("CoreWiki.Models.Article", b => { - b.Property("Topic") + b.Property("Slug") .HasColumnType("TEXT"); b.Property("Content") .IsRequired() .HasColumnType("TEXT"); - b.Property("Published") + b.Property("PublishedDateTime") + .HasColumnType("TEXT") + .HasColumnName("Published"); + + b.Property("Topic") + .IsRequired() + .HasMaxLength(100) .HasColumnType("TEXT"); - b.HasKey("Topic"); + b.HasKey("Slug"); b.ToTable("Articles"); + + b.HasData( + new + { + Slug = "home-page", + Content = "Welcome to your new CoreWiki installation", + PublishedDateTime = new DateTime(2023, 12, 22, 13, 41, 24, 978, DateTimeKind.Utc).AddTicks(110), + Topic = "Home Page" + }); }); #pragma warning restore 612, 618 } diff --git a/CoreWiki/Models/ApplicationDbContext.cs b/CoreWiki/Models/ApplicationDbContext.cs index 48b5dcf..38c3787 100644 --- a/CoreWiki/Models/ApplicationDbContext.cs +++ b/CoreWiki/Models/ApplicationDbContext.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using NodaTime; namespace CoreWiki.Models; @@ -8,7 +9,13 @@ public class ApplicationDbContext : DbContext public ApplicationDbContext(DbContextOptions options) : base(options) { - } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Entity
().HasData( + new Article { Topic = "Home Page", Slug = "home-page", Content = "Welcome to your new CoreWiki installation" } + ); + } } \ No newline at end of file diff --git a/CoreWiki/Models/Article.cs b/CoreWiki/Models/Article.cs index 53c2706..b989573 100644 --- a/CoreWiki/Models/Article.cs +++ b/CoreWiki/Models/Article.cs @@ -2,23 +2,32 @@ using NodaTime; using NodaTime.Extensions; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using CoreWiki.Utils; namespace CoreWiki.Models; public class Article { - [Required, Key] + [Key] + public string Slug { get; set; } + + [Required, MaxLength(100)] public string Topic { get; set; } + [NotMapped] public Instant Published { get; set; } = SystemClock.Instance.GetCurrentInstant(); + [Obsolete("This property is only for serialization")] [DataType(DataType.DateTime)] [Column("Published")] + [Required] public DateTime PublishedDateTime { get => Published.ToDateTimeUtc(); set => Published = DateTime.SpecifyKind(value, DateTimeKind.Utc).ToInstant(); } + [DataType(DataType.MultilineText)] - public string Content { get; set; } + [Required] + public string Content { get; set; } = default!; } \ No newline at end of file diff --git a/CoreWiki/Pages/All.cshtml b/CoreWiki/Pages/All.cshtml new file mode 100644 index 0000000..ca06cb5 --- /dev/null +++ b/CoreWiki/Pages/All.cshtml @@ -0,0 +1,48 @@ +@page +@model CoreWiki.Pages.All + +@{ + ViewData["Title"] = "All articles"; +} + +

All articles

+ +@foreach (var item in Model.Articles) +{ +
+
+

+ @item.Topic +

+
+ @item.Published +
+ + Edit + Delete +
+
+} + +
+ +
+ + +
+
\ No newline at end of file diff --git a/CoreWiki/Pages/All.cshtml.cs b/CoreWiki/Pages/All.cshtml.cs new file mode 100644 index 0000000..c41e216 --- /dev/null +++ b/CoreWiki/Pages/All.cshtml.cs @@ -0,0 +1,39 @@ +using CoreWiki.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Internal; + +namespace CoreWiki.Pages; + +public class All : PageModel +{ + private readonly ApplicationDbContext _context; + + [BindProperty(SupportsGet = true)] + public int PageNumber { get; set; } = 1; + [BindProperty(SupportsGet = true)] + public int PageSize { get; set; } = 25; + public IEnumerable
? Articles { get; set; } + public int TotalPages { get; set; } + + public All(ApplicationDbContext context) + { + _context = context; + } + + public async Task OnGetAsync() + { + TotalPages = (int)Math.Ceiling(await _context.Articles.CountAsync() / (float)PageSize); + if (PageNumber > TotalPages) PageNumber = 1; + + Articles = await _context.Articles + .AsNoTracking() + .OrderBy(a => a.PublishedDateTime) + .Skip(PageSize * (PageNumber - 1)) + .Take(PageSize) + .ToArrayAsync(); + + return Page(); + } +} \ No newline at end of file diff --git a/CoreWiki/Pages/Create.cshtml b/CoreWiki/Pages/Create.cshtml index fc74317..4abbf11 100644 --- a/CoreWiki/Pages/Create.cshtml +++ b/CoreWiki/Pages/Create.cshtml @@ -9,8 +9,8 @@

Article


-
-
+
+
diff --git a/CoreWiki/Pages/Create.cshtml.cs b/CoreWiki/Pages/Create.cshtml.cs index d89b97b..0bf9327 100644 --- a/CoreWiki/Pages/Create.cshtml.cs +++ b/CoreWiki/Pages/Create.cshtml.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using CoreWiki.Models; +using CoreWiki.Utils; using NodaTime; namespace CoreWiki.Pages @@ -30,19 +31,26 @@ namespace CoreWiki.Pages public Article Article { get; set; } = default!; - // To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD public async Task OnPostAsync() { - if (!ModelState.IsValid || _context.Articles == null || Article == null) + ModelState.Remove("Article.Slug"); + if (!ModelState.IsValid) { return Page(); } + Article.Slug = SafeUrl.Create(true, Article.Topic); Article.Published = _clock.GetCurrentInstant(); + if (_context.Articles.Any(a => a.Slug == Article.Slug)) + { + ModelState.AddModelError("Article.Topic", "Article already exists"); + return Page(); + } + _context.Articles.Add(Article); await _context.SaveChangesAsync(); - return Redirect($"/{Article.Topic}"); + return Redirect($"/{Article.Slug}"); } } } diff --git a/CoreWiki/Pages/Delete.cshtml b/CoreWiki/Pages/Delete.cshtml index ec40822..0b680b8 100644 --- a/CoreWiki/Pages/Delete.cshtml +++ b/CoreWiki/Pages/Delete.cshtml @@ -1,4 +1,4 @@ -@page +@page "/Delete/{slug}" @model CoreWiki.Pages.DeleteModel @{ @@ -27,8 +27,8 @@ - + | - Back to List + Back to Home Page
diff --git a/CoreWiki/Pages/Delete.cshtml.cs b/CoreWiki/Pages/Delete.cshtml.cs index 9de563e..584dc48 100644 --- a/CoreWiki/Pages/Delete.cshtml.cs +++ b/CoreWiki/Pages/Delete.cshtml.cs @@ -19,42 +19,39 @@ namespace CoreWiki.Pages } [BindProperty] - public Article Article { get; set; } = default!; + public Article Article { get; set; } = default!; - public async Task OnGetAsync(string id) + public async Task OnGetAsync(string slug) { - if (id == null || _context.Articles == null) + if (slug == "home-page") { return NotFound(); } - - var article = await _context.Articles.FirstOrDefaultAsync(m => m.Topic == id); + + var article = await _context.Articles.FirstOrDefaultAsync(a => a.Slug == slug); if (article == null) { return NotFound(); } - else - { - Article = article; - } + + Article = article; return Page(); } - public async Task OnPostAsync(string id) + public async Task OnPostAsync(string slug) { - if (id == null || _context.Articles == null) + if (slug == "home-page") { return NotFound(); } - var article = await _context.Articles.FindAsync(id); + + var article = await _context.Articles.FirstOrDefaultAsync(a => a.Slug == slug); - if (article != null) - { - Article = article; - _context.Articles.Remove(Article); - await _context.SaveChangesAsync(); - } + if (article == null) return NotFound(); + Article = article; + _context.Articles.Remove(Article); + await _context.SaveChangesAsync(); return Redirect("/"); } diff --git a/CoreWiki/Pages/Details.cshtml b/CoreWiki/Pages/Details.cshtml index bf1a616..9f48f9f 100644 --- a/CoreWiki/Pages/Details.cshtml +++ b/CoreWiki/Pages/Details.cshtml @@ -1,8 +1,8 @@ -@page "{topicName?}" +@page "/{slug?}" @model CoreWiki.Pages.DetailsModel @{ - ViewData["Title"] = "Details"; + ViewData["Title"] = Model.Article.Topic; }

@Model.Article.Topic

@@ -11,8 +11,8 @@
- Edit - @if (Model.Article.Topic != "HomePage") + Edit + @if (Model.Article.Slug != "home-page") { | Back to Home } diff --git a/CoreWiki/Pages/Details.cshtml.cs b/CoreWiki/Pages/Details.cshtml.cs index 25ff6c0..e4100ac 100644 --- a/CoreWiki/Pages/Details.cshtml.cs +++ b/CoreWiki/Pages/Details.cshtml.cs @@ -11,33 +11,26 @@ namespace CoreWiki.Pages { public class DetailsModel : PageModel { - private readonly CoreWiki.Models.ApplicationDbContext _context; + private readonly ApplicationDbContext _context; - public DetailsModel(CoreWiki.Models.ApplicationDbContext context) + public DetailsModel(ApplicationDbContext context) { _context = context; } - public Article Article { get; set; } = default!; + public Article Article { get; set; } = default!; - public async Task OnGetAsync(string? topicName) + public async Task OnGetAsync(string? slug) { - topicName ??= "HomePage"; - - if (_context.Articles == null) - { - return NotFound(); - } + slug ??= "home-page"; - var article = await _context.Articles.FirstOrDefaultAsync(m => m.Topic == topicName); + var article = await _context.Articles.FirstOrDefaultAsync(a => a.Slug == slug); if (article == null) { return NotFound(); } - else - { - Article = article; - } + + Article = article; return Page(); } } diff --git a/CoreWiki/Pages/Edit.cshtml b/CoreWiki/Pages/Edit.cshtml index 7609348..8793034 100644 --- a/CoreWiki/Pages/Edit.cshtml +++ b/CoreWiki/Pages/Edit.cshtml @@ -1,4 +1,4 @@ -@page +@page "/Edit/{slug}" @using CoreWiki.Models @model CoreWiki.Pages.EditModel @@ -8,17 +8,15 @@

Edit

-

@Model.Article.Topic

-
+
-
+
+
- - - +

@Model.Article.Topic

diff --git a/CoreWiki/Pages/Edit.cshtml.cs b/CoreWiki/Pages/Edit.cshtml.cs index e3b11c2..46920cb 100644 --- a/CoreWiki/Pages/Edit.cshtml.cs +++ b/CoreWiki/Pages/Edit.cshtml.cs @@ -25,14 +25,9 @@ namespace CoreWiki.Pages [BindProperty] public Article Article { get; set; } = default!; - public async Task OnGetAsync(string id) + public async Task OnGetAsync(string slug) { - if (id == null || _context.Articles == null) - { - return NotFound(); - } - - var article = await _context.Articles.FirstOrDefaultAsync(m => m.Topic == id); + var article = await _context.Articles.FirstOrDefaultAsync(m => m.Slug == slug); if (article == null) { return NotFound(); @@ -40,9 +35,7 @@ namespace CoreWiki.Pages Article = article; return Page(); } - - // To protect from overposting attacks, enable the specific properties you want to bind to. - // For more details, see https://aka.ms/RazorPagesCRUD. + public async Task OnPostAsync() { if (!ModelState.IsValid) @@ -69,12 +62,12 @@ namespace CoreWiki.Pages } } - return Redirect($"./{(Article.Topic == "HomePage" ? "" : Article.Topic)}"); + return Redirect($"/{(Article.Slug == "home-page" ? "" : Article.Slug)}"); } private bool ArticleExists(string id) { - return (_context.Articles?.Any(e => e.Topic == id)).GetValueOrDefault(); + return (_context.Articles?.Any(e => e.Slug == id)).GetValueOrDefault(); } } } diff --git a/CoreWiki/Pages/LatestChanges.cshtml b/CoreWiki/Pages/LatestChanges.cshtml index 390c8ab..677887b 100644 --- a/CoreWiki/Pages/LatestChanges.cshtml +++ b/CoreWiki/Pages/LatestChanges.cshtml @@ -15,11 +15,11 @@ {
-

@item.Topic

+

@item.Topic

@item.Published
- Edit - Delete + Edit + Delete
} \ No newline at end of file diff --git a/CoreWiki/Pages/Shared/_Layout.cshtml b/CoreWiki/Pages/Shared/_Layout.cshtml index dbe5e47..ac74eba 100644 --- a/CoreWiki/Pages/Shared/_Layout.cshtml +++ b/CoreWiki/Pages/Shared/_Layout.cshtml @@ -7,14 +7,14 @@ - + @await RenderSectionAsync("Styles", required: false)
-