refactor!: move services and entities to common proj

This commit is contained in:
Oliver Booth 2024-03-02 00:43:56 +00:00
parent 652550a2fe
commit 1588f6c8f6
Signed by: oliverbooth
GPG Key ID: E60B570D1B7557B5
90 changed files with 301 additions and 193 deletions

View File

@ -1,7 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Blog.Configuration; using Microsoft.Extensions.Configuration;
using OliverBooth.Common.Data.Blog.Configuration;
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <summary> /// <summary>
/// Represents a session with the blog database. /// Represents a session with the blog database.

View File

@ -1,14 +1,14 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using SmartFormat; using SmartFormat;
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <inheritdoc /> /// <inheritdoc />
internal sealed class BlogPost : IBlogPost internal sealed class BlogPost : IBlogPost
{ {
/// <inheritdoc /> /// <inheritdoc />
[NotMapped] [NotMapped]
public IBlogAuthor Author { get; internal set; } = null!; public IAuthor Author { get; internal set; } = null!;
/// <inheritdoc /> /// <inheritdoc />
public string Body { get; set; } = string.Empty; public string Body { get; set; } = string.Empty;

View File

@ -1,14 +1,14 @@
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using SmartFormat; using SmartFormat;
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <inheritdoc /> /// <inheritdoc />
internal sealed class BlogPostDraft : IBlogPostDraft internal sealed class BlogPostDraft : IBlogPostDraft
{ {
/// <inheritdoc /> /// <inheritdoc />
[NotMapped] [NotMapped]
public IBlogAuthor Author { get; internal set; } = null!; public IAuthor Author { get; internal set; } = null!;
/// <inheritdoc /> /// <inheritdoc />
public string Body { get; set; } = string.Empty; public string Body { get; set; } = string.Empty;

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <summary> /// <summary>
/// An enumeration of the possible visibilities of a blog post. /// An enumeration of the possible visibilities of a blog post.

View File

@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace OliverBooth.Data.Blog.Configuration; namespace OliverBooth.Common.Data.Blog.Configuration;
internal sealed class BlogPostConfiguration : IEntityTypeConfiguration<BlogPost> internal sealed class BlogPostConfiguration : IEntityTypeConfiguration<BlogPost>
{ {

View File

@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace OliverBooth.Data.Blog.Configuration; namespace OliverBooth.Common.Data.Blog.Configuration;
internal sealed class BlogPostDraftConfiguration : IEntityTypeConfiguration<BlogPostDraft> internal sealed class BlogPostDraftConfiguration : IEntityTypeConfiguration<BlogPostDraft>
{ {

View File

@ -1,9 +1,9 @@
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <summary> /// <summary>
/// Represents the author of a blog post. /// Represents the author of a blog post.
/// </summary> /// </summary>
public interface IBlogAuthor public interface IAuthor
{ {
/// <summary> /// <summary>
/// Gets the URL of the author's avatar. /// Gets the URL of the author's avatar.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <summary> /// <summary>
/// Represents a blog post. /// Represents a blog post.
@ -9,7 +9,7 @@ public interface IBlogPost
/// Gets the author of the post. /// Gets the author of the post.
/// </summary> /// </summary>
/// <value>The author of the post.</value> /// <value>The author of the post.</value>
IBlogAuthor Author { get; } IAuthor Author { get; }
/// <summary> /// <summary>
/// Gets or sets the body of the post. /// Gets or sets the body of the post.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Blog; namespace OliverBooth.Common.Data.Blog;
/// <summary> /// <summary>
/// Represents a draft of a blog post. /// Represents a draft of a blog post.
@ -9,7 +9,7 @@ public interface IBlogPostDraft
/// Gets the author of the post. /// Gets the author of the post.
/// </summary> /// </summary>
/// <value>The author of the post.</value> /// <value>The author of the post.</value>
IBlogAuthor Author { get; } IAuthor Author { get; }
/// <summary> /// <summary>
/// Gets or sets the body of the post. /// Gets or sets the body of the post.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data; namespace OliverBooth.Common.Data;
/// <summary> /// <summary>
/// Represents a permission. /// Represents a permission.

View File

@ -1,6 +1,6 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace OliverBooth.Data; namespace OliverBooth.Common.Data.ValueConverters;
internal sealed class PermissionListConverter : ValueConverter<IReadOnlyList<Permission>, string> internal sealed class PermissionListConverter : ValueConverter<IReadOnlyList<Permission>, string>
{ {

View File

@ -3,7 +3,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Books;
/// <summary> /// <summary>
/// Represents a book. /// Represents a book.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Books;
/// <summary> /// <summary>
/// Represents the state of a book. /// Represents the state of a book.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Books;
/// <summary> /// <summary>
/// Represents a book. /// Represents a book.

View File

@ -1,7 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using OliverBooth.Common.Data.Web.Contact;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
/// <summary> /// <summary>
/// Represents the configuration for the <see cref="BlacklistEntry" /> entity. /// Represents the configuration for the <see cref="BlacklistEntry" /> entity.

View File

@ -1,8 +1,9 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using OliverBooth.Common.Data.Web.Books;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
/// <summary> /// <summary>
/// Represents the configuration for the <see cref="Book" /> entity. /// Represents the configuration for the <see cref="Book" /> entity.

View File

@ -1,7 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using OliverBooth.Common.Data.Web.Projects;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
/// <summary> /// <summary>
/// Represents the configuration for the <see cref="ProgrammingLanguage" /> entity. /// Represents the configuration for the <see cref="ProgrammingLanguage" /> entity.

View File

@ -1,8 +1,9 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using OliverBooth.Common.Data.Web.Projects;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
/// <summary> /// <summary>
/// Represents the configuration for the <see cref="Project" /> entity. /// Represents the configuration for the <see cref="Project" /> entity.

View File

@ -1,8 +1,9 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using OliverBooth.Common.Data.Web.Users;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
internal sealed class SessionConfiguration : IEntityTypeConfiguration<Session> internal sealed class SessionConfiguration : IEntityTypeConfiguration<Session>
{ {

View File

@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
/// <summary> /// <summary>
/// Represents the configuration for the <see cref="SiteConfiguration" /> entity. /// Represents the configuration for the <see cref="SiteConfiguration" /> entity.

View File

@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
/// <summary> /// <summary>
/// Represents the configuration for the <see cref="Template" /> entity. /// Represents the configuration for the <see cref="Template" /> entity.

View File

@ -1,7 +1,9 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using OliverBooth.Common.Data.ValueConverters;
using OliverBooth.Common.Data.Web.Users;
namespace OliverBooth.Data.Web.Configuration; namespace OliverBooth.Common.Data.Web.Configuration;
internal sealed class UserConfiguration : IEntityTypeConfiguration<User> internal sealed class UserConfiguration : IEntityTypeConfiguration<User>
{ {

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Contact;
/// <inheritdoc cref="IBlacklistEntry"/> /// <inheritdoc cref="IBlacklistEntry"/>
internal sealed class BlacklistEntry : IEquatable<BlacklistEntry>, IBlacklistEntry internal sealed class BlacklistEntry : IEquatable<BlacklistEntry>, IBlacklistEntry

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Contact;
/// <summary> /// <summary>
/// Represents an entry in the blacklist. /// Represents an entry in the blacklist.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web;
/// <summary> /// <summary>
/// Represents a template. /// Represents a template.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Projects;
/// <summary> /// <summary>
/// Represents a programming language. /// Represents a programming language.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Projects;
/// <summary> /// <summary>
/// Represents a project. /// Represents a project.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Projects;
/// <inheritdoc cref="IProgrammingLanguage" /> /// <inheritdoc cref="IProgrammingLanguage" />
internal sealed class ProgrammingLanguage : IEquatable<ProgrammingLanguage>, IProgrammingLanguage internal sealed class ProgrammingLanguage : IEquatable<ProgrammingLanguage>, IProgrammingLanguage

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Projects;
/// <summary> /// <summary>
/// Represents a project. /// Represents a project.

View File

@ -1,6 +1,6 @@
using System.ComponentModel; using System.ComponentModel;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Projects;
/// <summary> /// <summary>
/// Represents the status of a project. /// Represents the status of a project.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web;
/// <summary> /// <summary>
/// Represents a site configuration item. /// Represents a site configuration item.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web;
/// <summary> /// <summary>
/// Represents a MediaWiki-style template. /// Represents a MediaWiki-style template.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
/// <summary> /// <summary>
/// Represents a temporary token used to correlate MFA attempts with the user. /// Represents a temporary token used to correlate MFA attempts with the user.
@ -34,4 +34,4 @@ public interface IMfaToken
/// </summary> /// </summary>
/// <value>The user.</value> /// <value>The user.</value>
IUser User { get; } IUser User { get; }
} }

View File

@ -1,6 +1,6 @@
using System.Net; using System.Net;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
/// <summary> /// <summary>
/// Represents a login session. /// Represents a login session.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
/// <summary> /// <summary>
/// Represents a user which can log in to the blog. /// Represents a user which can log in to the blog.

View File

@ -1,6 +1,6 @@
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
/// <summary> /// <summary>
/// An enumeration of possible results for <see cref="IUserService.VerifyMfaRequest" />. /// An enumeration of possible results for <see cref="IUserService.VerifyMfaRequest" />.

View File

@ -1,4 +1,4 @@
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
internal sealed class MfaToken : IMfaToken internal sealed class MfaToken : IMfaToken
{ {

View File

@ -1,6 +1,6 @@
using System.Net; using System.Net;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
internal sealed class Session : ISession internal sealed class Session : ISession
{ {

View File

@ -2,15 +2,15 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using Cysharp.Text; using Cysharp.Text;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OtpNet; using OtpNet;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web.Users;
/// <summary> /// <summary>
/// Represents a user. /// Represents a user.
/// </summary> /// </summary>
internal sealed class User : IUser, IBlogAuthor internal sealed class User : IUser, IAuthor
{ {
/// <inheritdoc cref="IUser.AvatarUrl" /> /// <inheritdoc cref="IUser.AvatarUrl" />
[NotMapped] [NotMapped]

View File

@ -1,7 +1,12 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Web.Configuration; using Microsoft.Extensions.Configuration;
using OliverBooth.Common.Data.Web.Books;
using OliverBooth.Common.Data.Web.Configuration;
using OliverBooth.Common.Data.Web.Contact;
using OliverBooth.Common.Data.Web.Projects;
using OliverBooth.Common.Data.Web.Users;
namespace OliverBooth.Data.Web; namespace OliverBooth.Common.Data.Web;
/// <summary> /// <summary>
/// Represents a session with the web database. /// Represents a session with the web database.

View File

@ -0,0 +1,32 @@
using Microsoft.Extensions.DependencyInjection;
using OliverBooth.Common.Data.Blog;
using OliverBooth.Common.Data.Web;
using OliverBooth.Common.Services;
using X10D.Hosting.DependencyInjection;
namespace OliverBooth.Common.Extensions;
/// <summary>
/// Extension methods for dependency injection.
/// </summary>
public static class DependencyInjectionExtensions
{
/// <summary>
/// Adds all required services provided by the assembly to the current <see cref="IServiceCollection" />.
/// </summary>
/// <param name="collection">The <see cref="IServiceCollection" /> to add the service to.</param>
public static void AddCommonServices(this IServiceCollection collection)
{
collection.AddDbContextFactory<BlogContext>();
collection.AddDbContextFactory<WebContext>();
collection.AddSingleton<IBlogPostService, BlogPostService>();
collection.AddSingleton<IContactService, ContactService>();
collection.AddSingleton<IProjectService, ProjectService>();
collection.AddSingleton<IReadingListService, ReadingListService>();
collection.AddSingleton<ITemplateService, TemplateService>();
collection.AddHostedSingleton<ISessionService, SessionService>();
collection.AddHostedSingleton<IUserService, UserService>();
}
}

View File

@ -1,7 +1,7 @@
using System.Globalization; using System.Globalization;
using SmartFormat.Core.Extensions; using SmartFormat.Core.Extensions;
namespace OliverBooth.Formatting; namespace OliverBooth.Common.Formatting;
/// <summary> /// <summary>
/// Represents a SmartFormat formatter that formats a date. /// Represents a SmartFormat formatter that formats a date.

View File

@ -1,7 +1,8 @@
using Markdig; using Markdig;
using Microsoft.Extensions.DependencyInjection;
using SmartFormat.Core.Extensions; using SmartFormat.Core.Extensions;
namespace OliverBooth.Formatting; namespace OliverBooth.Common.Formatting;
/// <summary> /// <summary>
/// Represents a SmartFormat formatter that formats markdown. /// Represents a SmartFormat formatter that formats markdown.

View File

@ -1,8 +1,8 @@
using Markdig; using Markdig;
using Markdig.Renderers; using Markdig.Renderers;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Markdown.Template; namespace OliverBooth.Common.Markdown.Template;
/// <summary> /// <summary>
/// Represents a Markdown extension that adds support for MediaWiki-style templates. /// Represents a Markdown extension that adds support for MediaWiki-style templates.

View File

@ -1,6 +1,6 @@
using Markdig.Syntax.Inlines; using Markdig.Syntax.Inlines;
namespace OliverBooth.Markdown.Template; namespace OliverBooth.Common.Markdown.Template;
/// <summary> /// <summary>
/// Represents a Markdown inline element that represents a MediaWiki-style template. /// Represents a Markdown inline element that represents a MediaWiki-style template.

View File

@ -2,7 +2,7 @@ using Cysharp.Text;
using Markdig.Helpers; using Markdig.Helpers;
using Markdig.Parsers; using Markdig.Parsers;
namespace OliverBooth.Markdown.Template; namespace OliverBooth.Common.Markdown.Template;
/// <summary> /// <summary>
/// Represents a Markdown inline parser that handles MediaWiki-style templates. /// Represents a Markdown inline parser that handles MediaWiki-style templates.
@ -17,7 +17,7 @@ public sealed class TemplateInlineParser : InlineParser
/// </summary> /// </summary>
public TemplateInlineParser() public TemplateInlineParser()
{ {
OpeningCharacters = new[] { '{' }; OpeningCharacters = ['{'];
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -1,8 +1,8 @@
using Markdig.Renderers; using Markdig.Renderers;
using Markdig.Renderers.Html; using Markdig.Renderers.Html;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Markdown.Template; namespace OliverBooth.Common.Markdown.Template;
/// <summary> /// <summary>
/// Represents a Markdown object renderer that handles <see cref="TemplateInline" /> elements. /// Represents a Markdown object renderer that handles <see cref="TemplateInline" /> elements.

View File

@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Alexinea.Extensions.Configuration.Toml" Version="7.0.0"/>
<PackageReference Include="Asp.Versioning.Mvc" Version="8.0.0"/>
<PackageReference Include="BCrypt.Net-Core" Version="1.6.0"/>
<PackageReference Include="Humanizer.Core" Version="2.14.1"/>
<PackageReference Include="Markdig" Version="0.35.0"/>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0"/>
<PackageReference Include="NetBarcode" Version="1.7.0"/>
<PackageReference Include="Otp.NET" Version="1.3.0"/>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0"/>
<PackageReference Include="Serilog" Version="3.1.1"/>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1"/>
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1"/>
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
<PackageReference Include="SmartFormat.NET" Version="3.3.2"/>
<PackageReference Include="X10D" Version="3.3.1"/>
<PackageReference Include="X10D.Hosting" Version="3.3.1"/>
<PackageReference Include="ZString" Version="2.5.1"/>
</ItemGroup>
<ItemGroup>
<Folder Include="Markdown\"/>
</ItemGroup>
</Project>

View File

@ -2,16 +2,28 @@ using System.Diagnostics.CodeAnalysis;
using Humanizer; using Humanizer;
using Markdig; using Markdig;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents an implementation of <see cref="IBlogPostService" />. /// Represents an implementation of <see cref="IBlogPostService" />.
/// </summary> /// </summary>
internal sealed class BlogPostService : IBlogPostService internal sealed class BlogPostService : IBlogPostService
{ {
/*private static readonly JsonSerializerOptions EditorJsOptions = new()
{
ReferenceHandler = ReferenceHandler.Preserve,
Converters =
{
new ParagraphBlockConverter(),
new HeadingBlockConverter(),
new MarkdownDocumentConverter()
}
};
*/
private readonly IDbContextFactory<BlogContext> _dbContextFactory; private readonly IDbContextFactory<BlogContext> _dbContextFactory;
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly MarkdownPipeline _markdownPipeline; private readonly MarkdownPipeline _markdownPipeline;
@ -33,6 +45,19 @@ internal sealed class BlogPostService : IBlogPostService
_markdownPipeline = markdownPipeline; _markdownPipeline = markdownPipeline;
} }
/// <inheritdoc />
public string GetBlogPostEditorObject(IBlogPost post)
{
if (post is null)
{
throw new ArgumentNullException(nameof(post));
}
/*var document = (JsonDocument)Markdig.Markdown.Convert(post.Body, new JsonRenderer(), _markdownPipeline);
return JsonSerializer.Serialize(document, EditorJsOptions);*/
return """{"blocks":{}}""";
}
/// <inheritdoc /> /// <inheritdoc />
public int GetBlogPostCount() public int GetBlogPostCount()
{ {
@ -196,7 +221,7 @@ internal sealed class BlogPostService : IBlogPostService
return post; return post;
} }
if (_userService.TryGetUser(post.AuthorId, out IUser? user) && user is IBlogAuthor author) if (_userService.TryGetUser(post.AuthorId, out IUser? user) && user is IAuthor author)
{ {
post.Author = author; post.Author = author;
} }

View File

@ -1,7 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web;
using OliverBooth.Common.Data.Web.Contact;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <inheritdoc cref="IContactService" /> /// <inheritdoc cref="IContactService" />
internal sealed class ContactService : IContactService internal sealed class ContactService : IContactService

View File

@ -1,7 +1,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service for managing blog posts. /// Represents a service for managing blog posts.
@ -27,6 +27,14 @@ public interface IBlogPostService
/// <returns>The total number of blog posts.</returns> /// <returns>The total number of blog posts.</returns>
int GetBlogPostCount(); int GetBlogPostCount();
/// <summary>
/// Returns a JSON object representing the blog post block data.
/// </summary>
/// <param name="post">The blog post whose block data object should be returned.</param>
/// <returns>The JSON data of the blog post block data.</returns>
/// <exception cref="ArgumentNullException"><paramref name="post" /> is <see langword="null" />.</exception>
string GetBlogPostEditorObject(IBlogPost post);
/// <summary> /// <summary>
/// Returns a collection of blog posts from the specified page, optionally limiting the number of posts /// Returns a collection of blog posts from the specified page, optionally limiting the number of posts
/// returned per page. /// returned per page.

View File

@ -1,6 +1,6 @@
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Contact;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service for managing contact information. /// Represents a service for managing contact information.

View File

@ -1,7 +1,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Projects;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service for interacting with projects. /// Represents a service for interacting with projects.

View File

@ -1,6 +1,6 @@
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Books;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service which fetches books from the reading list. /// Represents a service which fetches books from the reading list.

View File

@ -1,9 +1,10 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
using ISession = OliverBooth.Data.Web.ISession; using ISession = OliverBooth.Common.Data.Web.Users.ISession;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
public interface ISessionService public interface ISessionService
{ {

View File

@ -1,8 +1,8 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web;
using OliverBooth.Markdown.Template; using OliverBooth.Common.Markdown.Template;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service that renders MediaWiki-style templates. /// Represents a service that renders MediaWiki-style templates.

View File

@ -1,10 +1,10 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service for managing users. /// Represents a service which manages users.
/// </summary> /// </summary>
public interface IUserService public interface IUserService
{ {
@ -34,15 +34,16 @@ public interface IUserService
void DeleteToken(string token); void DeleteToken(string token);
/// <summary> /// <summary>
/// Attempts to find a user with the specified ID. /// Attempts to find a user by their unique ID.
/// </summary> /// </summary>
/// <param name="id">The ID of the user to find.</param> /// <param name="id">The ID of the user to return.</param>
/// <param name="user"> /// <param name="user">
/// When this method returns, contains the user with the specified ID, if the user is found; otherwise, /// When this method returns, contains the user whose ID is equal to the specified <paramref name="id" />, if
/// <see langword="null" />. /// such a user exists; otherwise, <see langword="null" />.
/// </param> /// </param>
/// <returns> /// <returns>
/// <see langword="true" /> if a user with the specified ID is found; otherwise, <see langword="false" />. /// <see langword="true" /> if a user was found with the specified <paramref name="id" />; otherwise,
/// <see langword="false" />.
/// </returns> /// </returns>
bool TryGetUser(Guid id, [NotNullWhen(true)] out IUser? user); bool TryGetUser(Guid id, [NotNullWhen(true)] out IUser? user);

View File

@ -2,9 +2,10 @@ using System.Diagnostics.CodeAnalysis;
using Humanizer; using Humanizer;
using Markdig; using Markdig;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web;
using OliverBooth.Common.Data.Web.Projects;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service for interacting with projects. /// Represents a service for interacting with projects.

View File

@ -1,7 +1,8 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web;
using OliverBooth.Common.Data.Web.Books;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
internal sealed class ReadingListService : IReadingListService internal sealed class ReadingListService : IReadingListService
{ {

View File

@ -1,13 +1,16 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ChangeTracking;
using OliverBooth.Data.Blog; using Microsoft.Extensions.Hosting;
using OliverBooth.Data.Web; using Microsoft.Extensions.Logging;
using ISession = OliverBooth.Data.Web.ISession; using OliverBooth.Common.Data.Web;
using OliverBooth.Common.Data.Web.Users;
using ISession = OliverBooth.Common.Data.Web.Users.ISession;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
internal sealed class SessionService : BackgroundService, ISessionService internal sealed class SessionService : BackgroundService, ISessionService
{ {
@ -20,11 +23,9 @@ internal sealed class SessionService : BackgroundService, ISessionService
/// </summary> /// </summary>
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
/// <param name="userService">The user service.</param> /// <param name="userService">The user service.</param>
/// <param name="blogContextFactory">The <see cref="BlogContext" /> factory.</param>
/// <param name="webContextFactory">The <see cref="WebContext" /> factory.</param> /// <param name="webContextFactory">The <see cref="WebContext" /> factory.</param>
public SessionService(ILogger<SessionService> logger, public SessionService(ILogger<SessionService> logger,
IUserService userService, IUserService userService,
IDbContextFactory<BlogContext> blogContextFactory,
IDbContextFactory<WebContext> webContextFactory) IDbContextFactory<WebContext> webContextFactory)
{ {
_logger = logger; _logger = logger;

View File

@ -1,13 +1,13 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web;
using OliverBooth.Formatting; using OliverBooth.Common.Formatting;
using OliverBooth.Markdown.Template; using OliverBooth.Common.Markdown.Template;
using SmartFormat; using SmartFormat;
using SmartFormat.Extensions; using SmartFormat.Extensions;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary> /// <summary>
/// Represents a service that renders MediaWiki-style templates. /// Represents a service that renders MediaWiki-style templates.
@ -22,7 +22,7 @@ internal sealed class TemplateService : ITemplateService
/// Initializes a new instance of the <see cref="TemplateService" /> class. /// Initializes a new instance of the <see cref="TemplateService" /> class.
/// </summary> /// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider" />.</param> /// <param name="serviceProvider">The <see cref="IServiceProvider" />.</param>
/// <param name="webContextFactory">The <see cref="WebContext" /> factory.</param> /// <param name="webContextFactory">The <see cref="Data.Web.WebContext" /> factory.</param>
public TemplateService(IServiceProvider serviceProvider, public TemplateService(IServiceProvider serviceProvider,
IDbContextFactory<WebContext> webContextFactory) IDbContextFactory<WebContext> webContextFactory)
{ {

View File

@ -2,15 +2,14 @@ using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography; using System.Security.Cryptography;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using OliverBooth.Data.Web; using Microsoft.Extensions.Hosting;
using OliverBooth.Common.Data.Web;
using OliverBooth.Common.Data.Web.Users;
using BC = BCrypt.Net.BCrypt; using BC = BCrypt.Net.BCrypt;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
namespace OliverBooth.Services; namespace OliverBooth.Common.Services;
/// <summary>
/// Represents an implementation of <see cref="IUserService" />.
/// </summary>
internal sealed class UserService : BackgroundService, IUserService internal sealed class UserService : BackgroundService, IUserService
{ {
private static readonly RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create(); private static readonly RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create();
@ -117,19 +116,8 @@ internal sealed class UserService : BackgroundService, IUserService
/// <inheritdoc /> /// <inheritdoc />
public bool TryGetUser(Guid id, [NotNullWhen(true)] out IUser? user) public bool TryGetUser(Guid id, [NotNullWhen(true)] out IUser? user)
{ {
if (_userCache.TryGetValue(id, out user))
{
return true;
}
using WebContext context = _dbContextFactory.CreateDbContext(); using WebContext context = _dbContextFactory.CreateDbContext();
user = context.Users.Find(id); user = context.Users.FirstOrDefault(u => u.Id == id);
if (user is not null)
{
_userCache.TryAdd(id, user);
}
return user is not null; return user is not null;
} }
@ -138,7 +126,12 @@ internal sealed class UserService : BackgroundService, IUserService
{ {
using WebContext context = _dbContextFactory.CreateDbContext(); using WebContext context = _dbContextFactory.CreateDbContext();
user = context.Users.FirstOrDefault(u => u.EmailAddress == email); user = context.Users.FirstOrDefault(u => u.EmailAddress == email);
return user is not null && BC.Verify(password, ((User)user).Password); if (user is not null && !BC.Verify(password, ((User)user).Password))
{
user = null;
}
return user is not null;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Gulpfile.mjs = Gulpfile.mjs Gulpfile.mjs = Gulpfile.mjs
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OliverBooth.Common", "OliverBooth.Common\OliverBooth.Common.csproj", "{77DC9941-E648-442F-935A-C66FC401ECBC}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -23,6 +25,10 @@ Global
{A58A6FA3-480C-400B-822A-3786741BF39C}.Debug|Any CPU.Build.0 = Debug|Any CPU {A58A6FA3-480C-400B-822A-3786741BF39C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A58A6FA3-480C-400B-822A-3786741BF39C}.Release|Any CPU.ActiveCfg = Release|Any CPU {A58A6FA3-480C-400B-822A-3786741BF39C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A58A6FA3-480C-400B-822A-3786741BF39C}.Release|Any CPU.Build.0 = Release|Any CPU {A58A6FA3-480C-400B-822A-3786741BF39C}.Release|Any CPU.Build.0 = Release|Any CPU
{77DC9941-E648-442F-935A-C66FC401ECBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77DC9941-E648-442F-935A-C66FC401ECBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77DC9941-E648-442F-935A-C66FC401ECBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77DC9941-E648-442F-935A-C66FC401ECBC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
EndGlobalSection EndGlobalSection

View File

@ -1,9 +1,9 @@
using System.Diagnostics; using System.Diagnostics;
using Asp.Versioning; using Asp.Versioning;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
using OliverBooth.Services; using OliverBooth.Common.Services;
using ISession = OliverBooth.Data.Web.ISession; using ISession = OliverBooth.Common.Data.Web.Users.ISession;
namespace OliverBooth.Controllers.Api.v1; namespace OliverBooth.Controllers.Api.v1;

View File

@ -1,8 +1,9 @@
using Asp.Versioning; using Asp.Versioning;
using Humanizer; using Humanizer;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
using OliverBooth.Common.Services;
using OliverBooth.Services; using OliverBooth.Services;
namespace OliverBooth.Controllers.Api.v1; namespace OliverBooth.Controllers.Api.v1;

View File

@ -1,6 +1,7 @@
using System.Xml.Serialization; using System.Xml.Serialization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Common.Services;
using OliverBooth.Data.Blog.Rss; using OliverBooth.Data.Blog.Rss;
using OliverBooth.Services; using OliverBooth.Services;

View File

@ -1,7 +1,7 @@
using System.Text; using System.Text;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Contact;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Controllers; namespace OliverBooth.Controllers;

View File

@ -13,7 +13,7 @@ public sealed class TimestampInlineParser : InlineParser
/// </summary> /// </summary>
public TimestampInlineParser() public TimestampInlineParser()
{ {
OpeningCharacters = new[] { '<' }; OpeningCharacters = ['<'];
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -27,32 +27,17 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Alexinea.Extensions.Configuration.Toml" Version="7.0.0"/>
<PackageReference Include="Asp.Versioning.Mvc" Version="8.0.0"/>
<PackageReference Include="AspNetCore.ReCaptcha" Version="1.8.1"/> <PackageReference Include="AspNetCore.ReCaptcha" Version="1.8.1"/>
<PackageReference Include="BCrypt.Net-Core" Version="1.6.0"/>
<PackageReference Include="FluentFTP" Version="49.0.2" />
<PackageReference Include="FluentFTP.Logging" Version="1.0.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.59"/> <PackageReference Include="HtmlAgilityPack" Version="1.11.59"/>
<PackageReference Include="Humanizer.Core" Version="2.14.1"/>
<PackageReference Include="MailKit" Version="4.3.0"/> <PackageReference Include="MailKit" Version="4.3.0"/>
<PackageReference Include="MailKitSimplified.Sender" Version="2.9.0"/> <PackageReference Include="MailKitSimplified.Sender" Version="2.9.0"/>
<PackageReference Include="Markdig" Version="0.35.0"/>
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.2"/> <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.2"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.2"/> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.2"/>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.2"/> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.2"/>
<PackageReference Include="NetBarcode" Version="1.7.0"/> </ItemGroup>
<PackageReference Include="Otp.NET" Version="1.3.0"/>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0"/> <ItemGroup>
<PackageReference Include="Serilog" Version="3.1.1"/> <ProjectReference Include="..\OliverBooth.Common\OliverBooth.Common.csproj"/>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1"/>
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1"/>
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
<PackageReference Include="SmartFormat.NET" Version="3.3.2"/>
<PackageReference Include="X10D" Version="3.3.1"/>
<PackageReference Include="X10D.Hosting" Version="3.3.1"/>
<PackageReference Include="ZString" Version="2.5.1"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,8 +1,10 @@
@page "/admin/blog-posts" @page "/admin/blog-posts"
@using System.Diagnostics @using System.Diagnostics
@using OliverBooth.Data @using Microsoft.AspNetCore.Mvc.TagHelpers
@using OliverBooth.Data.Blog @using OliverBooth.Common.Data
@using OliverBooth.Data.Web @using OliverBooth.Common.Data.Blog
@using OliverBooth.Common.Data.Web.Users
@using OliverBooth.Common.Services
@using OliverBooth.Services @using OliverBooth.Services
@model OliverBooth.Pages.Admin.BlogPosts @model OliverBooth.Pages.Admin.BlogPosts
@inject IBlogPostService BlogPostService @inject IBlogPostService BlogPostService
@ -52,7 +54,7 @@
<th>Options</th> <th>Options</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (IBlogPost post in BlogPostService.GetAllBlogPosts(visibility: (BlogPostVisibility)(-1))) @foreach (IBlogPost post in BlogPostService.GetAllBlogPosts(visibility: (BlogPostVisibility)(-1)))
{ {

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Pages.Admin; namespace OliverBooth.Pages.Admin;

View File

@ -1,6 +1,6 @@
@page "/admin/blog-posts/edit/{id}" @page "/admin/blog-posts/edit/{id}"
@using Markdig @using Markdig
@using OliverBooth.Data.Blog @using OliverBooth.Common.Data.Blog
@model OliverBooth.Pages.Admin.EditBlogPost @model OliverBooth.Pages.Admin.EditBlogPost
@inject MarkdownPipeline MarkdownPipeline @inject MarkdownPipeline MarkdownPipeline

View File

@ -1,7 +1,8 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
using OliverBooth.Common.Services;
using OliverBooth.Services; using OliverBooth.Services;
namespace OliverBooth.Pages.Admin; namespace OliverBooth.Pages.Admin;

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Users;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Pages.Admin; namespace OliverBooth.Pages.Admin;

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Pages.Admin; namespace OliverBooth.Pages.Admin;

View File

@ -1,5 +1,5 @@
@page "/admin/login/mfa" @page "/admin/login/mfa"
@using OliverBooth.Data.Web @using OliverBooth.Common.Data.Web.Users
@model OliverBooth.Pages.Admin.MultiFactorStep @model OliverBooth.Pages.Admin.MultiFactorStep
@{ @{

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Pages.Admin; namespace OliverBooth.Pages.Admin;

View File

@ -1,6 +1,7 @@
@page "/blog/{year:int}/{month:int}/{day:int}/{slug}" @page "/blog/{year:int}/{month:int}/{day:int}/{slug}"
@using Humanizer @using Humanizer
@using OliverBooth.Data.Blog @using OliverBooth.Common.Data.Blog
@using OliverBooth.Common.Services
@using OliverBooth.Services @using OliverBooth.Services
@inject IBlogPostService BlogPostService @inject IBlogPostService BlogPostService
@model Article @model Article
@ -29,7 +30,7 @@
@{ @{
ViewData["Post"] = post; ViewData["Post"] = post;
ViewData["Title"] = post.Title; ViewData["Title"] = post.Title;
IBlogAuthor author = post.Author; IAuthor author = post.Author;
DateTimeOffset published = post.Published; DateTimeOffset published = post.Published;
} }

View File

@ -1,7 +1,8 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Common.Services;
using OliverBooth.Services; using OliverBooth.Services;
using BC = BCrypt.Net.BCrypt; using BC = BCrypt.Net.BCrypt;

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Common.Services;
using OliverBooth.Services; using OliverBooth.Services;
namespace OliverBooth.Pages.Blog; namespace OliverBooth.Pages.Blog;

View File

@ -1,7 +1,8 @@
using Cysharp.Text; using Cysharp.Text;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Blog; using OliverBooth.Common.Data.Blog;
using OliverBooth.Common.Services;
using OliverBooth.Services; using OliverBooth.Services;
namespace OliverBooth.Pages.Blog; namespace OliverBooth.Pages.Blog;

View File

@ -1,5 +1,5 @@
@page @page
@using OliverBooth.Data.Web @using OliverBooth.Common.Data.Web.Books
@model OliverBooth.Pages.Books @model OliverBooth.Pages.Books
@{ @{
ViewData["Title"] = "Reading List"; ViewData["Title"] = "Reading List";

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Books;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Pages; namespace OliverBooth.Pages;

View File

@ -1,6 +1,6 @@
@page @page
@using OliverBooth.Data.Web @using OliverBooth.Common.Data.Web.Contact
@using OliverBooth.Services @using OliverBooth.Common.Services
@inject IContactService ContactService @inject IContactService ContactService
@{ @{
ViewData["Title"] = "Blacklist"; ViewData["Title"] = "Blacklist";

View File

@ -1,6 +1,6 @@
@page @page
@using OliverBooth.Data.Web @using OliverBooth.Common.Data.Web.Projects
@using OliverBooth.Services @using OliverBooth.Common.Services
@inject IProjectService ProjectService @inject IProjectService ProjectService
@{ @{
ViewData["Title"] = "Projects"; ViewData["Title"] = "Projects";

View File

@ -1,7 +1,7 @@
@page "/project/{slug}" @page "/project/{slug}"
@using Markdig @using Markdig
@using OliverBooth.Data.Web @using OliverBooth.Common.Data.Web.Projects
@using OliverBooth.Services @using OliverBooth.Common.Services
@model Project @model Project
@inject IProjectService ProjectService @inject IProjectService ProjectService
@inject MarkdownPipeline MarkdownPipeline @inject MarkdownPipeline MarkdownPipeline

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using OliverBooth.Data.Web; using OliverBooth.Common.Data.Web.Projects;
using OliverBooth.Services; using OliverBooth.Common.Services;
namespace OliverBooth.Pages.Projects; namespace OliverBooth.Pages.Projects;

View File

@ -1,6 +1,8 @@
@using OliverBooth.Data.Blog @using OliverBooth.Data.Blog
@using OliverBooth.Data.Web
@using OliverBooth.Services @using OliverBooth.Services
@using OliverBooth.Common.Data.Web.Users
@using OliverBooth.Common.Services
@using OliverBooth.Common.Data.Blog
@inject IBlogPostService BlogPostService @inject IBlogPostService BlogPostService
@inject IUserService UserService @inject IUserService UserService
@inject ISessionService SessionService @inject ISessionService SessionService

View File

@ -1,6 +1,8 @@
@using OliverBooth.Data.Blog @using OliverBooth.Data.Blog
@using OliverBooth.Data.Web
@using OliverBooth.Services @using OliverBooth.Services
@using OliverBooth.Common.Data.Web.Users
@using OliverBooth.Common.Services
@using OliverBooth.Common.Data.Blog
@inject IBlogPostService BlogPostService @inject IBlogPostService BlogPostService
@inject IUserService UserService @inject IUserService UserService
@inject ISessionService SessionService @inject ISessionService SessionService

View File

@ -4,15 +4,15 @@ using AspNetCore.ReCaptcha;
using FluentFTP; using FluentFTP;
using FluentFTP.Logging; using FluentFTP.Logging;
using Markdig; using Markdig;
using OliverBooth.Common.Extensions;
using OliverBooth.Common.Markdown.Template;
using OliverBooth.Common.Services;
using OliverBooth.Data.Blog; using OliverBooth.Data.Blog;
using OliverBooth.Data.Web;
using OliverBooth.Extensions; using OliverBooth.Extensions;
using OliverBooth.Markdown.Template;
using OliverBooth.Markdown.Timestamp; using OliverBooth.Markdown.Timestamp;
using OliverBooth.Services; using OliverBooth.Services;
using Serilog; using Serilog;
using Serilog.Extensions.Logging; using Serilog.Extensions.Logging;
using X10D.Hosting.DependencyInjection;
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.WriteTo.Console() .WriteTo.Console()
@ -44,8 +44,7 @@ builder.Services.AddApiVersioning(options =>
options.ApiVersionReader = new UrlSegmentApiVersionReader(); options.ApiVersionReader = new UrlSegmentApiVersionReader();
}); });
builder.Services.AddDbContextFactory<BlogContext>(); builder.Services.AddCommonServices();
builder.Services.AddDbContextFactory<WebContext>();
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddTransient<IAsyncFtpClient, AsyncFtpClient>(provider => builder.Services.AddTransient<IAsyncFtpClient, AsyncFtpClient>(provider =>
{ {
@ -66,14 +65,7 @@ builder.Services.AddTransient<IAsyncFtpClient, AsyncFtpClient>(provider =>
}); });
builder.Services.AddSingleton<ICdnService, CdnService>(); builder.Services.AddSingleton<ICdnService, CdnService>();
builder.Services.AddSingleton<IContactService, ContactService>();
builder.Services.AddSingleton<ITemplateService, TemplateService>();
builder.Services.AddSingleton<IBlogPostService, BlogPostService>();
builder.Services.AddSingleton<IProjectService, ProjectService>();
builder.Services.AddSingleton<IMastodonService, MastodonService>(); builder.Services.AddSingleton<IMastodonService, MastodonService>();
builder.Services.AddSingleton<IReadingListService, ReadingListService>();
builder.Services.AddHostedSingleton<IUserService, UserService>();
builder.Services.AddHostedSingleton<ISessionService, SessionService>();
builder.Services.AddRazorPages().AddRazorRuntimeCompilation(); builder.Services.AddRazorPages().AddRazorRuntimeCompilation();
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
builder.Services.AddRazorComponents().AddInteractiveServerComponents(); builder.Services.AddRazorComponents().AddInteractiveServerComponents();