Skip to content

Commit

Permalink
feat: Reworking NanoBlog
Browse files Browse the repository at this point in the history
- Templates are now defined in main configuration  rather then different
  structure files
- Posts may have a template, "{NAME}" can be used for id tags
- Data / export directories can now be configured and empty presets
  were removed
- Updated README and Swagger documentation
- Update version to 0.2.0
  • Loading branch information
its-laika committed Oct 23, 2024
1 parent e2ed719 commit f9c4c7a
Show file tree
Hide file tree
Showing 57 changed files with 507 additions and 906 deletions.
25 changes: 0 additions & 25 deletions .dockerignore

This file was deleted.

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ _ReSharper.Caches/
.DS_Store
.vscode/
*.Dot[sS]ettings.user
global.json
global.json
blog-files/
blog-export/
docker/data/*
25 changes: 10 additions & 15 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@ MIT License

Copyright (c) 2022-2024 Niklas Schmidt

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ private static ResourceExecutingContext BuildContext(string? authenticationToken
RouteData = new RouteData(),
ActionDescriptor = new ActionDescriptor()
},
new List<IFilterMetadata>(),
new List<IValueProviderFactory>()
[],
[]
);

return actionExecutedContext;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using NanoBlog.Containers;

namespace NanoBlog.Test.Services.MimeTypes.MimeTypeProvider;

public class ProvideMimeTypeAsyncByFileName
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using NanoBlog.Containers;
using NanoBlog.Extensions;

namespace NanoBlog.Test.Services.MimeTypes.MimeTypeProvider;

public class ProvideMimeTypeAsyncByFormFile
Expand Down Expand Up @@ -108,7 +105,7 @@ private static IFormFile BuildFormFile(string fileName, string? mimeType)
headers[HeaderNames.ContentType] = new StringValues(mimeType);
}

return new FormFile(new MemoryStream(Array.Empty<byte>()), 0, 0, fileName, fileName)
return new FormFile(new MemoryStream([]), 0, 0, fileName, fileName)
{
Headers = headers
};
Expand Down
3 changes: 2 additions & 1 deletion NanoBlog.Test/Usings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.AspNetCore.Mvc.Abstractions;
global using Microsoft.AspNetCore.Mvc.Filters;
global using Microsoft.AspNetCore.Mvc.ModelBinding;
global using Microsoft.AspNetCore.Routing;
global using Microsoft.Extensions.Primitives;
global using Microsoft.Net.Http.Headers;
global using NanoBlog.Containers;
global using NanoBlog.Extensions;
global using System.Text;
global using Xunit;
3 changes: 3 additions & 0 deletions NanoBlog/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bin
obj
*.Development.json
6 changes: 3 additions & 3 deletions NanoBlog/Attributes/AuthenticationActionFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace NanoBlog.Attributes;

public class AuthenticationActionFilter(string configuredAuthenticationToken) : IResourceFilter
{
private const string _AUTHENTICATION_HEADER_BEARER_PREFIX = "Bearer ";
private const string AuthenticationHeaderBearerPrefix = "Bearer ";

public void OnResourceExecuting(ResourceExecutingContext context)
{
Expand All @@ -13,13 +13,13 @@ public void OnResourceExecuting(ResourceExecutingContext context)
return;
}

if (!token.StartsWith(_AUTHENTICATION_HEADER_BEARER_PREFIX, StringComparison.InvariantCultureIgnoreCase))
if (!token.StartsWith(AuthenticationHeaderBearerPrefix, StringComparison.InvariantCultureIgnoreCase))
{
context.Result = new UnauthorizedResult();
return;
}

var givenAuthenticationToken = token[_AUTHENTICATION_HEADER_BEARER_PREFIX.Length..].Trim();
var givenAuthenticationToken = token[AuthenticationHeaderBearerPrefix.Length..].Trim();

if (string.IsNullOrEmpty(givenAuthenticationToken))
{
Expand Down
6 changes: 3 additions & 3 deletions NanoBlog/Attributes/FileNameValidationAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class All() : ValidFileName(AllRegex());
[GeneratedRegex(@"^[A-Za-z0-9\-]+\.(png|jpg|jpeg|gif|svg|txt|html)")]
private static partial Regex AllRegex();

private const int _MAX_FILE_LENGTH = 100;
private const int MaxFileLength = 100;
private readonly Regex _validFileNameRegex;

private ValidFileName(Regex validFileNameRegex)
Expand All @@ -33,9 +33,9 @@ private ValidFileName(Regex validFileNameRegex)
return new ValidationResult($"Attributed value is not of type {typeof(string)}");
}

if (fileName.Length > _MAX_FILE_LENGTH)
if (fileName.Length > MaxFileLength)
{
return new ValidationResult($"File name exceeded max length ({_MAX_FILE_LENGTH}).");
return new ValidationResult($"File name exceeded max length ({MaxFileLength}).");
}

return _validFileNameRegex.IsMatch(fileName)
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
79 changes: 57 additions & 22 deletions NanoBlog/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,40 +1,75 @@
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
// ReSharper disable MemberCanBePrivate.Global

namespace NanoBlog;

public class Configuration : IConfiguration
{
public bool UsePagination { get; init; } = IConfiguration.DEFAULT_USE_PAGINATION;
public int PageSize { get; init; } = IConfiguration.DEFAULT_PAGE_SIZE;
public string Language { get; init; } = IConfiguration.DEFAULT_LANGUAGE;
public string BlogRootServerDirectory { get; init; } = IConfiguration.DEFAULT_BLOG_ROOT_SERVER_DIRECTORY;
public ICollection<string> ExportKeepFileNames { get; } = new List<string>();
public string PagePlaceholderPosts { get; init; } = string.Empty;
public string PagePlaceholderNavigation { get; init; } = string.Empty;
public string PostPlaceholderContent { get; init; } = string.Empty;
public string PostPlaceholderName { get; init; } = string.Empty;

public static DirectoryInfo GetStageAssetsDirectoryInfo()
public bool UsePagination { get; init; } = false;
public string PageTemplate { get; init; } = string.Empty;
public string PostTemplate { get; init; } = string.Empty;
public int? PageSize { get; init; } = null;

public string PostDirectory { get; init; } = string.Empty;
public string AssetDirectory { get; init; } = string.Empty;

public string ExportDirectory { get; init; } = string.Empty;

public ICollection<string> KeepExportFiles { get; init; } = [];

public DirectoryInfo GetAssetsDirectoryInfo()
{
EnsureNotEmpty(AssetDirectory);
return EnsureExisting(Path.Combine(Directory.GetCurrentDirectory(), AssetDirectory));
}

public DirectoryInfo GetPostsDirectoryInfo()
{
EnsureNotEmpty(PostDirectory);
return EnsureExisting(Path.Combine(Directory.GetCurrentDirectory(), PostDirectory));
}

public DirectoryInfo GetExportDirectoryInfo()
{
EnsureNotEmpty(ExportDirectory);
return EnsureExisting(Path.Combine(Directory.GetCurrentDirectory(), ExportDirectory));
}

public DirectoryInfo GetExportAssetsDirectoryInfo()
{
return new DirectoryInfo(
Path.Combine(Directory.GetCurrentDirectory(), IConfiguration.STAGE_ASSETS_DIRECTORY_NAME)
);
EnsureNotEmpty(ExportDirectory);
return EnsureExisting(Path.Combine(Directory.GetCurrentDirectory(), ExportDirectory, "assets"));
}

public static DirectoryInfo GetStagePostsDirectoryInfo()
public DirectoryInfo GetExportArchiveDirectoryInfo()
{
return new DirectoryInfo(
Path.Combine(Directory.GetCurrentDirectory(), IConfiguration.STAGE_POSTS_DIRECTORY_NAME)
);
EnsureNotEmpty(ExportDirectory);
return EnsureExisting(Path.Combine(Directory.GetCurrentDirectory(), ExportDirectory, "archive"));
}

public static DirectoryInfo GetStageStructureDirectoryInfo()
private static DirectoryInfo EnsureExisting(string path)
{
return new DirectoryInfo(
Path.Combine(Directory.GetCurrentDirectory(), IConfiguration.STAGE_STRUCTURE_DIRECTORY_NAME)
);
var directoryInfo = new DirectoryInfo(path);

if (!directoryInfo.Exists)
{
directoryInfo.Create();
}

return directoryInfo.EnsureSecureMode();
}

public static DirectoryInfo GetExportDirectoryInfo()
private static void EnsureNotEmpty(string path)
{
return new DirectoryInfo(
Path.Combine(Directory.GetCurrentDirectory(), IConfiguration.EXPORT_DIRECTORY_NAME)
);
if (!string.IsNullOrWhiteSpace(path))
{
return;
}

throw new Exception("Path not configured");
}
}
6 changes: 0 additions & 6 deletions NanoBlog/Containers/GeneratedPageContentsContainer.cs

This file was deleted.

9 changes: 0 additions & 9 deletions NanoBlog/Containers/IStageDirectoryContainer.cs

This file was deleted.

3 changes: 1 addition & 2 deletions NanoBlog/Containers/PostExcerpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ namespace NanoBlog.Containers;

public record PostExcerpt(
string Name,
string Excerpt
);
string Excerpt);
26 changes: 0 additions & 26 deletions NanoBlog/Containers/StageDirectoryContainer.cs

This file was deleted.

15 changes: 0 additions & 15 deletions NanoBlog/Containers/StageFilesContentContainer.cs

This file was deleted.

Loading

0 comments on commit f9c4c7a

Please sign in to comment.