Added some helpers, a new logger and log migration and modified the router
This commit is contained in:
parent
69b50275cd
commit
afb3a7f3a3
10 changed files with 666 additions and 13 deletions
252
Moonlight/App/Helpers/Formatter.cs
Normal file
252
Moonlight/App/Helpers/Formatter.cs
Normal file
|
@ -0,0 +1,252 @@
|
|||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class Formatter
|
||||
{
|
||||
public static string GenerateString(int length)
|
||||
{
|
||||
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var stringBuilder = new StringBuilder();
|
||||
var random = new Random();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
stringBuilder.Append(chars[random.Next(chars.Length)]);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string IntToStringWithLeadingZeros(int number, int n)
|
||||
{
|
||||
string result = number.ToString();
|
||||
int length = result.Length;
|
||||
|
||||
for (int i = length; i < n; i++)
|
||||
{
|
||||
result = "0" + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string CapitalizeFirstCharacter(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
char firstChar = char.ToUpper(input[0]);
|
||||
string restOfString = input.Substring(1);
|
||||
|
||||
return firstChar + restOfString;
|
||||
}
|
||||
|
||||
public static string CutInHalf(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return input;
|
||||
|
||||
int length = input.Length;
|
||||
int halfLength = length / 2;
|
||||
|
||||
return input.Substring(0, halfLength);
|
||||
}
|
||||
|
||||
public static bool EndsInOneOf(string suffix, IEnumerable<string> strings)
|
||||
{
|
||||
foreach (string str in strings)
|
||||
{
|
||||
if (suffix.EndsWith(str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ContainsOneOf(string textToSearch, IEnumerable<string> strings, out string foundText)
|
||||
{
|
||||
foreach (string str in strings)
|
||||
{
|
||||
if (textToSearch.Contains(str))
|
||||
{
|
||||
foundText = str;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foundText = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ContainsOneOf(string textToSearch, IEnumerable<string> strings)
|
||||
{
|
||||
return ContainsOneOf(textToSearch, strings, out _);
|
||||
}
|
||||
|
||||
public static string FormatSize(long bytes)
|
||||
{
|
||||
var i = Math.Abs(bytes) / 1024D;
|
||||
if (i < 1)
|
||||
{
|
||||
return bytes + " B";
|
||||
}
|
||||
else if (i / 1024D < 1)
|
||||
{
|
||||
return i.Round(2) + " KB";
|
||||
}
|
||||
else if (i / (1024D * 1024D) < 1)
|
||||
{
|
||||
return (i / 1024D).Round(2) + " MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
return (i / (1024D * 1024D)).Round(2) + " GB";
|
||||
}
|
||||
}
|
||||
|
||||
private static double Round(this double d, int decimals)
|
||||
{
|
||||
return Math.Round(d, decimals);
|
||||
}
|
||||
|
||||
public static string ReplaceEnd(string input, string substringToReplace, string newSubstring)
|
||||
{
|
||||
int lastIndexOfSubstring = input.LastIndexOf(substringToReplace);
|
||||
if (lastIndexOfSubstring >= 0)
|
||||
{
|
||||
input = input.Remove(lastIndexOfSubstring, substringToReplace.Length)
|
||||
.Insert(lastIndexOfSubstring, newSubstring);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public static string ConvertCamelCaseToSpaces(string input)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (char.IsUpper(c))
|
||||
{
|
||||
output.Append(' ');
|
||||
}
|
||||
|
||||
output.Append(c);
|
||||
}
|
||||
|
||||
return output.ToString().Trim();
|
||||
}
|
||||
|
||||
public static string FormatUptime(double uptime)
|
||||
{
|
||||
TimeSpan t = TimeSpan.FromMilliseconds(uptime);
|
||||
|
||||
return FormatUptime(t);
|
||||
}
|
||||
|
||||
public static string FormatUptime(TimeSpan t)
|
||||
{
|
||||
if (t.Days > 0)
|
||||
{
|
||||
return $"{t.Days}d {t.Hours}h {t.Minutes}m {t.Seconds}s";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{t.Hours}h {t.Minutes}m {t.Seconds}s";
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatDate(DateTime e)
|
||||
{
|
||||
string i2s(int i)
|
||||
{
|
||||
if (i.ToString().Length < 2)
|
||||
return "0" + i;
|
||||
return i.ToString();
|
||||
}
|
||||
|
||||
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year} {i2s(e.Hour)}:{i2s(e.Minute)}";
|
||||
}
|
||||
|
||||
public static string FormatDateOnly(DateTime e)
|
||||
{
|
||||
string i2s(int i)
|
||||
{
|
||||
if (i.ToString().Length < 2)
|
||||
return "0" + i;
|
||||
return i.ToString();
|
||||
}
|
||||
|
||||
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year}";
|
||||
}
|
||||
|
||||
public static string FormatSize(double bytes)
|
||||
{
|
||||
var i = Math.Abs(bytes) / 1024D;
|
||||
if (i < 1)
|
||||
{
|
||||
return bytes + " B";
|
||||
}
|
||||
else if (i / 1024D < 1)
|
||||
{
|
||||
return i.Round(2) + " KB";
|
||||
}
|
||||
else if (i / (1024D * 1024D) < 1)
|
||||
{
|
||||
return (i / 1024D).Round(2) + " MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
return (i / (1024D * 1024D)).Round(2) + " GB";
|
||||
}
|
||||
}
|
||||
|
||||
public static RenderFragment FormatLineBreaks(string content)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
int i = 0;
|
||||
var arr = content.Split("\n", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
|
||||
foreach (var line in arr)
|
||||
{
|
||||
builder.AddContent(i, line);
|
||||
if (i++ != arr.Length - 1)
|
||||
{
|
||||
builder.AddMarkupContent(i, "<br/>");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This will replace every placeholder with the respective value if specified in the model
|
||||
// For example:
|
||||
// A instance of the user model has been passed in the 'models' parameter of the function.
|
||||
// So the placeholder {{User.Email}} will be replaced by the value of the Email property of the model
|
||||
public static string ProcessTemplating(string text, params object[] models)
|
||||
{
|
||||
foreach (var model in models)
|
||||
{
|
||||
foreach (var property in model.GetType().GetProperties())
|
||||
{
|
||||
var value = property.GetValue(model);
|
||||
|
||||
if(value == null)
|
||||
continue;
|
||||
|
||||
var placeholder = "{{" + $"{model.GetType().Name}.{property.Name}" + "}}";
|
||||
|
||||
text = text.Replace(placeholder, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
172
Moonlight/App/Helpers/HashHelper.cs
Normal file
172
Moonlight/App/Helpers/HashHelper.cs
Normal file
|
@ -0,0 +1,172 @@
|
|||
using System.Security.Cryptography;
|
||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
// Src: https://codereview.stackexchange.com/questions/176697/net-core-mvc-future-proof-hashing-of-passwords
|
||||
public static class HashHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The default number of Iterations
|
||||
/// </summary>
|
||||
private const int DefaultIterations = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Provides Information about a specific Hash Version
|
||||
/// </summary>
|
||||
private class HashVersion
|
||||
{
|
||||
public short Version { get; set; }
|
||||
public int SaltSize { get; set; }
|
||||
public int HashSize { get; set; }
|
||||
public KeyDerivationPrf KeyDerivation { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds all possible Hash Versions
|
||||
/// </summary>
|
||||
private static readonly Dictionary<short, HashVersion> _versions = new Dictionary<short, HashVersion>
|
||||
{
|
||||
{
|
||||
1, new HashVersion
|
||||
{
|
||||
Version = 1,
|
||||
KeyDerivation = KeyDerivationPrf.HMACSHA512,
|
||||
HashSize = 256 / 8,
|
||||
SaltSize = 128 / 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The default Hash Version, which should be used, if a new Hash is Created
|
||||
/// </summary>
|
||||
private static HashVersion DefaultVersion => _versions[1];
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given hash uses the latest version
|
||||
/// </summary>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash of the latest version?</returns>
|
||||
public static bool IsLatestHashVersion(byte[] data)
|
||||
{
|
||||
var version = BitConverter.ToInt16(data, 0);
|
||||
return version == DefaultVersion.Version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given hash uses the latest version
|
||||
/// </summary>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash of the latest version?</returns>
|
||||
public static bool IsLatestHashVersion(string data)
|
||||
{
|
||||
var dataBytes = Convert.FromBase64String(data);
|
||||
return IsLatestHashVersion(dataBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random byte array
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the byte array</param>
|
||||
/// <returns>The random byte array</returns>
|
||||
public static byte[] GetRandomBytes(int length)
|
||||
{
|
||||
var data = new byte[length];
|
||||
using (var randomNumberGenerator = RandomNumberGenerator.Create())
|
||||
{
|
||||
randomNumberGenerator.GetBytes(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Hash of a clear text
|
||||
/// </summary>
|
||||
/// <param name="clearText">the clear text</param>
|
||||
/// <param name="iterations">the number of iteration the hash alogrythm should run</param>
|
||||
/// <returns>the Hash</returns>
|
||||
public static byte[] Hash(string clearText, int iterations = DefaultIterations)
|
||||
{
|
||||
//get current version
|
||||
var currentVersion = DefaultVersion;
|
||||
|
||||
//get the byte arrays of the hash and meta information
|
||||
var saltBytes = GetRandomBytes(currentVersion.SaltSize);
|
||||
var versionBytes = BitConverter.GetBytes(currentVersion.Version);
|
||||
var iterationBytes = BitConverter.GetBytes(iterations);
|
||||
var hashBytes = KeyDerivation.Pbkdf2(clearText, saltBytes, currentVersion.KeyDerivation, iterations,
|
||||
currentVersion.HashSize);
|
||||
|
||||
//calculate the indexes for the combined hash
|
||||
var indexVersion = 0;
|
||||
var indexIteration = indexVersion + 2;
|
||||
var indexSalt = indexIteration + 4;
|
||||
var indexHash = indexSalt + currentVersion.SaltSize;
|
||||
|
||||
//combine all data to one result hash
|
||||
var resultBytes = new byte[2 + 4 + currentVersion.SaltSize + currentVersion.HashSize];
|
||||
Array.Copy(versionBytes, 0, resultBytes, indexVersion, 2);
|
||||
Array.Copy(iterationBytes, 0, resultBytes, indexIteration, 4);
|
||||
Array.Copy(saltBytes, 0, resultBytes, indexSalt, currentVersion.SaltSize);
|
||||
Array.Copy(hashBytes, 0, resultBytes, indexHash, currentVersion.HashSize);
|
||||
return resultBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Hash of a clear text and convert it to a Base64 String representation
|
||||
/// </summary>
|
||||
/// <param name="clearText">the clear text</param>
|
||||
/// <param name="iterations">the number of iteration the hash alogrythm should run</param>
|
||||
/// <returns>the Hash</returns>
|
||||
public static string HashToString(string clearText, int iterations = DefaultIterations)
|
||||
{
|
||||
var data = Hash(clearText, iterations);
|
||||
return Convert.ToBase64String(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a given clear Text against a hash
|
||||
/// </summary>
|
||||
/// <param name="clearText">The clear text</param>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash equal to the clear text?</returns>
|
||||
public static bool Verify(string clearText, byte[] data)
|
||||
{
|
||||
//Get the current version and number of iterations
|
||||
var currentVersion = _versions[BitConverter.ToInt16(data, 0)];
|
||||
var iteration = BitConverter.ToInt32(data, 2);
|
||||
|
||||
//Create the byte arrays for the salt and hash
|
||||
var saltBytes = new byte[currentVersion.SaltSize];
|
||||
var hashBytes = new byte[currentVersion.HashSize];
|
||||
|
||||
//Calculate the indexes of the salt and the hash
|
||||
var indexSalt = 2 + 4; // Int16 (Version) and Int32 (Iteration)
|
||||
var indexHash = indexSalt + currentVersion.SaltSize;
|
||||
|
||||
//Fill the byte arrays with salt and hash
|
||||
Array.Copy(data, indexSalt, saltBytes, 0, currentVersion.SaltSize);
|
||||
Array.Copy(data, indexHash, hashBytes, 0, currentVersion.HashSize);
|
||||
|
||||
//Hash the current clearText with the parameters given via the data
|
||||
var verificationHashBytes = KeyDerivation.Pbkdf2(clearText, saltBytes, currentVersion.KeyDerivation, iteration,
|
||||
currentVersion.HashSize);
|
||||
|
||||
//Check if generated hashes are equal
|
||||
return hashBytes.SequenceEqual(verificationHashBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a given clear Text against a hash
|
||||
/// </summary>
|
||||
/// <param name="clearText">The clear text</param>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash equal to the clear text?</returns>
|
||||
public static bool Verify(string clearText, string data)
|
||||
{
|
||||
var dataBytes = Convert.FromBase64String(data);
|
||||
return Verify(clearText, dataBytes);
|
||||
}
|
||||
}
|
11
Moonlight/App/Helpers/LogMigrator/LogMigrateProvider.cs
Normal file
11
Moonlight/App/Helpers/LogMigrator/LogMigrateProvider.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace Moonlight.App.Helpers.LogMigrator;
|
||||
|
||||
public class LogMigrateProvider : ILoggerProvider
|
||||
{
|
||||
public void Dispose() {}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return new MigrateLogger();
|
||||
}
|
||||
}
|
53
Moonlight/App/Helpers/LogMigrator/MigrateLogger.cs
Normal file
53
Moonlight/App/Helpers/LogMigrator/MigrateLogger.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
namespace Moonlight.App.Helpers.LogMigrator;
|
||||
|
||||
public class MigrateLogger : ILogger
|
||||
{
|
||||
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogLevel.Critical:
|
||||
Logger.Fatal(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Fatal(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
Logger.Warn(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Warn(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Debug:
|
||||
Logger.Debug(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Debug(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
Logger.Error(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Error(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
Logger.Info(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Info(exception);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
112
Moonlight/App/Helpers/Logger.cs
Normal file
112
Moonlight/App/Helpers/Logger.cs
Normal file
|
@ -0,0 +1,112 @@
|
|||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Serilog;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class Logger
|
||||
{
|
||||
#region String logger
|
||||
public static void Verbose(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Verbose("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Info(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Information("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Debug(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Debug("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Error(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Error("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Warn(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Warning("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Fatal(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Fatal("{Message}", message);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exception method calls
|
||||
|
||||
public static void Verbose(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Verbose(exception, "");
|
||||
}
|
||||
|
||||
public static void Info(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Information(exception, "");
|
||||
}
|
||||
|
||||
public static void Debug(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Debug(exception, "");
|
||||
}
|
||||
|
||||
public static void Error(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Error(exception, "");
|
||||
}
|
||||
|
||||
public static void Warn(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Warning(exception, "");
|
||||
}
|
||||
|
||||
public static void Fatal(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Fatal(exception, "");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static string GetNameOfCallingClass(int skipFrames = 4)
|
||||
{
|
||||
string fullName;
|
||||
Type declaringType;
|
||||
|
||||
do
|
||||
{
|
||||
MethodBase method = new StackFrame(skipFrames, false).GetMethod();
|
||||
declaringType = method.DeclaringType;
|
||||
if (declaringType == null)
|
||||
{
|
||||
return method.Name;
|
||||
}
|
||||
|
||||
skipFrames++;
|
||||
if (declaringType.Name.Contains("<"))
|
||||
fullName = declaringType.ReflectedType.Name;
|
||||
else
|
||||
fullName = declaringType.Name;
|
||||
} while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase) |
|
||||
fullName.Contains("Logger"));
|
||||
|
||||
return fullName;
|
||||
}
|
||||
}
|
34
Moonlight/App/Helpers/PathBuilder.cs
Normal file
34
Moonlight/App/Helpers/PathBuilder.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class PathBuilder
|
||||
{
|
||||
public static string Dir(params string[] parts)
|
||||
{
|
||||
var res = "";
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
res += part + Path.DirectorySeparatorChar;
|
||||
}
|
||||
|
||||
return res.Replace(
|
||||
$"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}",
|
||||
$"{Path.DirectorySeparatorChar}"
|
||||
);
|
||||
}
|
||||
|
||||
public static string File(params string[] parts)
|
||||
{
|
||||
var res = "";
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
res += part + (part == parts.Last() ? "" : Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
return res.Replace(
|
||||
$"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}",
|
||||
$"{Path.DirectorySeparatorChar}"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
<Router AppAssembly="@typeof(BlazorApp).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<CascadingValue TValue="Type" Name="TargetPageType" Value="routeData.PageType">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
</CascadingValue>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
<Folder Include="App\Database\Enums\" />
|
||||
<Folder Include="App\Database\Migrations\" />
|
||||
<Folder Include="App\Exceptions\" />
|
||||
<Folder Include="App\Helpers\" />
|
||||
<Folder Include="App\Http\" />
|
||||
<Folder Include="App\Models\Abstractions\" />
|
||||
<Folder Include="App\Models\Enums\" />
|
||||
|
@ -28,4 +27,10 @@
|
|||
<Folder Include="App\Services\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Serilog" Version="3.1.0-dev-02078" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.0-dev-00923" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Moonlight.App.Extensions;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Helpers.LogMigrator;
|
||||
using Serilog;
|
||||
|
||||
Directory.CreateDirectory(PathBuilder.Dir("storage"));
|
||||
Directory.CreateDirectory(PathBuilder.Dir("storage", "logs"));
|
||||
|
||||
var logConfig = new LoggerConfiguration();
|
||||
|
||||
logConfig = logConfig.Enrich.FromLogContext()
|
||||
.WriteTo.Console(
|
||||
outputTemplate:
|
||||
"{Timestamp:HH:mm:ss} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}");
|
||||
|
||||
Log.Logger = logConfig.CreateLogger();
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
builder.Services.AddControllers();
|
||||
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Logging.AddProvider(new LogMigrateProvider());
|
||||
|
||||
var config =
|
||||
new ConfigurationBuilder().AddJsonString(
|
||||
|
@ -13,19 +32,11 @@ builder.Logging.AddConfiguration(config.Build());
|
|||
|
||||
var app = builder.Build();
|
||||
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
|
@ -2,4 +2,5 @@
|
|||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.JSInterop
|
||||
@using Moonlight
|
||||
@using Moonlight.App.Helpers
|
||||
@using Moonlight.Shared.Components.Partials
|
Loading…
Reference in a new issue