- fix: auth logic part 2
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Nebula.Shared.Configurations;
|
||||
|
||||
public abstract class ComplexConVarBinder<T> : INotifyPropertyChanged, INotifyPropertyChanging
|
||||
{
|
||||
private readonly ConVarObserver<T> _baseConVar;
|
||||
private readonly Lock _lock = new();
|
||||
private readonly SemaphoreSlim _valueChangeSemaphore = new(1, 1);
|
||||
|
||||
public T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _baseConVar.Value;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
_ = SetValueAsync(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected ComplexConVarBinder(ConVarObserver<T> baseConVar)
|
||||
{
|
||||
_baseConVar = baseConVar ?? throw new ArgumentNullException(nameof(baseConVar));
|
||||
_baseConVar.PropertyChanged += BaseConVarOnPropertyChanged;
|
||||
_baseConVar.PropertyChanging += BaseConVarOnPropertyChanging;
|
||||
}
|
||||
|
||||
|
||||
private async Task SetValueAsync(T? value)
|
||||
{
|
||||
await _valueChangeSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
var newValue = await OnValueChange(value).ConfigureAwait(false);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_baseConVar.Value = newValue;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_valueChangeSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Task<T?> OnValueChange(T? newValue);
|
||||
|
||||
private void BaseConVarOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
|
||||
}
|
||||
|
||||
private void BaseConVarOnPropertyChanging(object? sender, PropertyChangingEventArgs e)
|
||||
{
|
||||
PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(nameof(Value)));
|
||||
}
|
||||
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
public event PropertyChangingEventHandler? PropertyChanging;
|
||||
}
|
||||
@@ -12,6 +12,8 @@ public sealed class ConVarObserver<T> : IDisposable, INotifyPropertyChanged, INo
|
||||
private T? _value;
|
||||
private ConfigurationService.OnConfigurationChangedDelegate<T> _delegate;
|
||||
|
||||
public bool HasValue => Value != null;
|
||||
|
||||
public T? Value
|
||||
{
|
||||
get => _value;
|
||||
@@ -31,6 +33,7 @@ public sealed class ConVarObserver<T> : IDisposable, INotifyPropertyChanged, INo
|
||||
private void OnValueChanged(T? value)
|
||||
{
|
||||
OnPropertyChanging(nameof(Value));
|
||||
OnPropertyChanging(nameof(HasValue));
|
||||
|
||||
if(value is null && _value is null)
|
||||
return;
|
||||
@@ -39,17 +42,13 @@ public sealed class ConVarObserver<T> : IDisposable, INotifyPropertyChanged, INo
|
||||
|
||||
_value = value;
|
||||
OnPropertyChanged(nameof(Value));
|
||||
OnPropertyChanged(nameof(HasValue));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_convar.OnValueChanged -= OnValueChanged;
|
||||
}
|
||||
|
||||
public bool HasValue()
|
||||
{
|
||||
return Value != null;
|
||||
}
|
||||
|
||||
public static implicit operator T? (ConVarObserver<T> convar) => convar.Value;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using Nebula.Shared.FileApis;
|
||||
using Nebula.Shared.Services.Logging;
|
||||
using Robust.LoaderApi;
|
||||
|
||||
namespace Nebula.Shared.Services;
|
||||
|
||||
@@ -9,16 +8,23 @@ namespace Nebula.Shared.Services;
|
||||
public class DebugService : IDisposable
|
||||
{
|
||||
public static bool DoFileLog;
|
||||
private ServiceLogger Root {get; set;}
|
||||
|
||||
private readonly string _path =
|
||||
Path.Combine(FileService.RootPath, "log", Assembly.GetEntryAssembly()?.GetName().Name ?? "App");
|
||||
|
||||
|
||||
public DebugService()
|
||||
{
|
||||
ClearLog();
|
||||
Root = new ServiceLogger("Root",_path);
|
||||
Root.GetLogger("DebugService").Log("Initializing debug service " + (DoFileLog ? "with file logging" : "without file logging"));
|
||||
Root = new ServiceLogger("Root", _path);
|
||||
Root.GetLogger("DebugService")
|
||||
.Log("Initializing debug service " + (DoFileLog ? "with file logging" : "without file logging"));
|
||||
}
|
||||
|
||||
private ServiceLogger Root { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Root.Dispose();
|
||||
}
|
||||
|
||||
public ILogger GetLogger(string loggerName)
|
||||
@@ -31,25 +37,14 @@ public class DebugService : IDisposable
|
||||
return Root.GetLogger(objectToLog.GetType().Name);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Root.Dispose();
|
||||
}
|
||||
|
||||
private void ClearLog()
|
||||
{
|
||||
if(!Directory.Exists(_path))
|
||||
if (!Directory.Exists(_path))
|
||||
return;
|
||||
var di = new DirectoryInfo(_path);
|
||||
|
||||
foreach (var file in di.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
foreach (var dir in di.GetDirectories())
|
||||
{
|
||||
dir.Delete(true);
|
||||
}
|
||||
foreach (var file in di.GetFiles()) file.Delete();
|
||||
foreach (var dir in di.GetDirectories()) dir.Delete(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,101 +58,101 @@ public enum LoggerCategory
|
||||
internal class ServiceLogger : ILogger
|
||||
{
|
||||
private readonly string _directory;
|
||||
public ServiceLogger? Root { get; private set; }
|
||||
private readonly string _path;
|
||||
|
||||
public ServiceLogger(string category, string directory)
|
||||
{
|
||||
_directory = directory;
|
||||
Category = category;
|
||||
|
||||
if (!DebugService.DoFileLog) return;
|
||||
|
||||
if(!Directory.Exists(directory)) Directory.CreateDirectory(directory);
|
||||
|
||||
if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
|
||||
|
||||
_path = Path.Combine(directory, $"{Category}.log");
|
||||
|
||||
|
||||
File.Create(_path).Dispose();
|
||||
}
|
||||
|
||||
public string Category { get; init; }
|
||||
|
||||
private Dictionary<string, ServiceLogger> Childs { get; init; } = new();
|
||||
|
||||
private FileStream? _fileStream;
|
||||
private StreamWriter? _streamWriter;
|
||||
private readonly string _path;
|
||||
public ServiceLogger? Root { get; private set; }
|
||||
|
||||
public string Category { get; init; }
|
||||
private ConcurrentDictionary<string, ServiceLogger> Childs { get; } = new();
|
||||
|
||||
public ServiceLogger GetLogger(string category)
|
||||
{
|
||||
if (Childs.TryGetValue(category, out var logger))
|
||||
return logger;
|
||||
|
||||
logger = new ServiceLogger(category, _directory);
|
||||
logger.Root = this;
|
||||
Childs.Add(category, logger);
|
||||
return logger;
|
||||
}
|
||||
|
||||
public void Log(LoggerCategory loggerCategory, string message)
|
||||
{
|
||||
var output = DebugService.DoFileLog
|
||||
var output = DebugService.DoFileLog
|
||||
? $"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd HH:mm:ss}][{Enum.GetName(loggerCategory)}][{Category}]: {message}"
|
||||
: message;
|
||||
|
||||
Console.WriteLine(output);
|
||||
|
||||
LogToFile(output);
|
||||
}
|
||||
|
||||
private void LogToFile(string output)
|
||||
{
|
||||
if(!DebugService.DoFileLog) return;
|
||||
_fileStream = File.Open(_path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
|
||||
_streamWriter = new StreamWriter(_fileStream);
|
||||
Root?.LogToFile(output);
|
||||
_streamWriter.WriteLine(output);
|
||||
_streamWriter.Flush();
|
||||
|
||||
_streamWriter.Dispose();
|
||||
_fileStream.Dispose();
|
||||
|
||||
_fileStream = null;
|
||||
_streamWriter = null;
|
||||
Console.WriteLine(output);
|
||||
|
||||
LogToFile(output);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!DebugService.DoFileLog) return;
|
||||
|
||||
_streamWriter?.Dispose();
|
||||
_fileStream?.Dispose();
|
||||
|
||||
foreach (var (_, child) in Childs)
|
||||
{
|
||||
child.Dispose();
|
||||
}
|
||||
Childs.Clear();
|
||||
|
||||
Childs.Clear(); // Not strictly necessary, but keeps intent clear
|
||||
}
|
||||
|
||||
public ServiceLogger GetLogger(string category)
|
||||
{
|
||||
return Childs.GetOrAdd(category, key =>
|
||||
{
|
||||
var logger = new ServiceLogger(key, _directory)
|
||||
{
|
||||
Root = this
|
||||
};
|
||||
return logger;
|
||||
});
|
||||
}
|
||||
|
||||
private void LogToFile(string output)
|
||||
{
|
||||
if (!DebugService.DoFileLog) return;
|
||||
|
||||
try
|
||||
{
|
||||
Root?.LogToFile(output); // Log to parent first
|
||||
|
||||
using var fileStream = File.Open(_path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
|
||||
using var streamWriter = new StreamWriter(fileStream);
|
||||
streamWriter.WriteLine(output);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Console.WriteLine($"[Logging Error] Failed to write log: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
public static void Debug(this ILogger logger,string message)
|
||||
public static void Debug(this ILogger logger, string message)
|
||||
{
|
||||
logger.Log(LoggerCategory.Debug, message);
|
||||
}
|
||||
|
||||
public static void Error(this ILogger logger,string message)
|
||||
public static void Error(this ILogger logger, string message)
|
||||
{
|
||||
logger.Log(LoggerCategory.Error, message);
|
||||
}
|
||||
|
||||
public static void Log(this ILogger logger,string message)
|
||||
public static void Log(this ILogger logger, string message)
|
||||
{
|
||||
logger.Log(LoggerCategory.Log, message);
|
||||
}
|
||||
|
||||
public static void Error(this ILogger logger,Exception e)
|
||||
public static void Error(this ILogger logger, Exception e)
|
||||
{
|
||||
Error(logger,e.Message + "\r\n" + e.StackTrace);
|
||||
Error(logger, e.Message + "\r\n" + e.StackTrace);
|
||||
if (e.InnerException != null)
|
||||
Error(logger, e.InnerException);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user