Compare commits

...

1 Commits

Author SHA1 Message Date
986bc3853c begin new and last rework 2024-07-18 14:44:44 +02:00
41 changed files with 68 additions and 1156 deletions

View File

@@ -1,6 +1,6 @@
using OwnChar.Model;
namespace OwnChar.Api;
namespace OwnChar.Api.Managers;
public interface ICharacterManager
{
Character? CreateCharacter(string? name);

View File

@@ -1,6 +1,6 @@
using OwnChar.Model;
namespace OwnChar.Api;
namespace OwnChar.Api.Managers;
public interface IGroupsManager
{
IQueryable<Group>? GetGroups(UserProfile? profile);

View File

@@ -2,7 +2,7 @@
using OwnChar.Model;
using Pilz.Cryptography;
namespace OwnChar.Api;
namespace OwnChar.Api.Managers;
public interface IOwnCharManager
{
IDataManager? DataManager { get; set; }

View File

@@ -1,7 +1,7 @@
using OwnChar.Model;
using Pilz.Cryptography;
namespace OwnChar.Api;
namespace OwnChar.Api.Managers;
public interface IUserManager
{
IQueryable<UserAccount>? GetUserAccounts();

View File

@@ -0,0 +1,8 @@
using OwnChar.Api.Managers;
namespace OwnChar.Api;
public abstract class OwnCharManagerModule(IOwnCharManager manager)
{
public IOwnCharManager Manager { get; } = manager;
}

View File

@@ -0,0 +1,9 @@
using OwnChar.Model;
namespace OwnChar.Api.Responses;
public class LoginResponse
{
public UserAccount? UserAccount { get; set; }
public string? Secret { get; set; }
}

View File

@@ -0,0 +1,7 @@
namespace OwnChar.Api.Updates;
public class GroupUpdate
{
public int Id { get; set; }
public string? Name { get; set; }
}

View File

@@ -0,0 +1,5 @@
namespace OwnChar.Clients;
public class CharactersApiClient
{
}

View File

@@ -0,0 +1,5 @@
namespace OwnChar.Clients;
public class GroupsApiClient
{
}

View File

@@ -0,0 +1,5 @@
namespace OwnChar.Clients;
public class LoginApiClient
{
}

View File

@@ -0,0 +1,5 @@
namespace OwnChar.Clients;
public class UsersApiClient
{
}

View File

@@ -1,57 +0,0 @@
namespace OwnChar.Data;
public class DataManagerAction(string id)
{
public DataManagerAction? BaseAction { get; }
public string ActionId
{
get
{
if (BaseAction is not null)
return $"{BaseAction.ActionId}.{id}";
return id;
}
}
public DataManagerAction(DataManagerAction baseAction, string id) : this(id)
{
BaseAction = baseAction;
}
public static bool operator ==(DataManagerAction? a, DataManagerAction? b)
{
if (a is null || b is null)
return false;
if (a.ActionId == b.ActionId)
return true;
if (a.BaseAction is not null && a.BaseAction.ActionId == b.ActionId)
return true;
if (b.BaseAction is not null && a.ActionId == b.BaseAction.ActionId)
return true;
return false;
}
public static bool operator !=(DataManagerAction? a, DataManagerAction? b)
{
return !(a == b);
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj))
return true;
if (obj is not DataManagerAction action)
return false;
return action == this;
}
public override int GetHashCode()
{
return ActionId.GetHashCode();
}
}

View File

@@ -1,6 +0,0 @@
namespace OwnChar.Data;
public record class DataManagerActionResult(bool HasSuccess, object? Result)
{
public static DataManagerActionResult NonSuccess { get; } = new(false, null);
}

View File

@@ -1,9 +0,0 @@
namespace OwnChar.Data;
public enum DataManagerActionType
{
Default,
Get,
Set,
Delete,
}

View File

@@ -1,25 +0,0 @@
namespace OwnChar.Data;
public static class DataManagerActions
{
public static DataManagerAction Get { get; } = new("get");
public static DataManagerAction Save { get; } = new("save");
public static DataManagerAction Delete { get; } = new("delete");
public static DataManagerAction Associate { get; } = new("associate");
public static class Getter
{
public static DataManagerAction UserAccount { get; } = new(Get, "useraccount");
public static DataManagerAction Group { get; } = new(Get, "group");
public static DataManagerAction Character { get; } = new(Get, "character");
public static DataManagerAction Property { get; } = new(Get, "property");
public static DataManagerAction PropertyCategory { get; } = new(Get, "propertycategory");
}
public static class Association
{
public static DataManagerAction Owner { get; } = new(Associate, "owner");
public static DataManagerAction Profile { get; } = new(Associate, "profile");
public static DataManagerAction Members { get; } = new(Associate, "members");
}
}

View File

@@ -1,7 +0,0 @@
namespace OwnChar.Data;
public enum DataProviderSetAction
{
Set,
Remove,
}

View File

@@ -1,12 +0,0 @@
namespace OwnChar.Data;
public static class HierarchyProperties
{
public static string PropProps => "Props";
public static string PropPropCats => "PropCats";
public static string PropCharacters => "Characters";
public static string PropProfile => "Profile";
public static string PropOwner => "Owner";
public static string PropMembers => "Members";
public static string PropGroups => "Groups";
}

View File

@@ -1,19 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data;
public interface IDataManager
{
public delegate void OnActionEventHandler(object sender, OnActionEventArgs e);
public delegate void OnCallbackEventHandler(object sender, OnCallbackEventArgs e);
event OnActionEventHandler? OnAction;
event OnCallbackEventHandler? OnCallback;
// Login
UserAccount? Login(string username, string password);
bool Logout(UserAccount? account);
// Action
DataManagerActionResult ExecuteAction(DataManagerAction action, DataManagerActionType actionType, UserAccount currentUser, object? obj, params object?[] parameters);
}

View File

@@ -1,26 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data;
public interface IDataProvider
{
bool IsInitialized();
void SetInitialized();
bool SaveDatabase();
// Model
T? Create<T>() where T : OwnCharObject;
bool Save<T>(T obj) where T : OwnCharObject;
bool Delete<T>(T obj) where T : OwnCharObject;
IQueryable<T>? GetAll<T>() where T : OwnCharObject;
// Hierarchy
bool SetChild(OwnCharObject parent, OwnCharObject? child, string property, DataProviderSetAction action);
T? GetChild<T>(OwnCharObject parent, string property) where T : OwnCharObject;
IQueryable<T>? GetChilds<T>(OwnCharObject parent, string property) where T : OwnCharObject;
T? GetParent<T>(OwnCharObject child, string property) where T : OwnCharObject;
// Explicite getters
UserAccount? GetUserAccount(string username, string password);
UserProfile? GetUserProfile(string username);
}

View File

@@ -1,416 +0,0 @@
using OwnChar.Manager.Modules;
using OwnChar.Model;
using System.Reflection.Metadata;
namespace OwnChar.Data.Managers;
public class DefaultDataManager : IDataManager
{
public event IDataManager.OnActionEventHandler? OnAction;
public event IDataManager.OnCallbackEventHandler? OnCallback;
private const string defaultUsername = "admin";
private const string defaultPassword = "admin";
public IDataProvider DataProvider { get; }
public DefaultDataManager(IDataProvider dataProvider)
{
DataProvider = dataProvider;
Initialize(false);
}
public virtual DataManagerActionResult ExecuteAction(DataManagerAction action, DataManagerActionType actionType, UserAccount currentUser, object? obj, params object?[] parameters)
{
var success = false;
var e = new OnActionEventArgs(action, actionType, currentUser, obj, parameters);
OnAction?.Invoke(this, e);
if (e.IsHandled)
return new(true, e.Result);
if (HandleGet(e)
|| HandleDelete(e)
|| HandleSave(e)
|| HandleAssociation(e))
success = true;
OnCallback?.Invoke(this, new(action, actionType, success, e.Result));
return new(success, e.Result);
}
protected virtual bool HandleGet(OnActionEventArgs e)
{
if (!e.Is(DataManagerActions.Get))
return false;
// Character
if (e.Is(DataManagerActions.Getter.Character))
{
// Get
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.User))
{
if (e.GetObject(out Group? group))
return e.SetResult(DataProvider.GetChilds<Character>(group, HierarchyProperties.PropCharacters));
if (e.GetObject(out UserProfile? profile))
return e.SetResult(DataProvider.GetChilds<Character>(profile, HierarchyProperties.PropCharacters));
}
if (e.Is(UserType.Admin))
return e.SetResult(DataProvider.GetAll<Character>());
}
// Create
else if (e.Is(DataManagerActionType.Set))
{
if (e.GetObject(out Group? group) && e.GetParam(0, out string? name))
return e.SetResult(CreateCharacter(e.CurrentUser, name, group));
}
}
// Group
else if (e.Is(DataManagerActions.Getter.Group))
{
// Get
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.User))
{
if (e.GetObject(out UserProfile? profile))
return e.SetResult(DataProvider.GetChilds<Group>(profile, HierarchyProperties.PropGroups));
}
if (e.Is(UserType.Admin))
return e.SetResult(DataProvider.GetAll<Group>());
}
// Create
else if (e.Is(DataManagerActionType.Set))
{
if (e.GetParam(0, out string? name))
return e.SetResult(CreateGroup(e.CurrentUser, name));
}
}
// User
else if (e.Is(DataManagerActions.Getter.UserAccount))
{
// Get
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.Admin))
return e.SetResult(DataProvider.GetAll<UserAccount>());
}
// Create
if (e.Is(DataManagerActionType.Set))
{
if (e.GetParam(0, out string? username) && e.GetParam(1, out string? password))
return e.SetResult(CreateUserAccount(username, password));
}
}
// Property
else if (e.Is(DataManagerActions.Getter.Property))
{
// Get
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.User) && e.GetObject(out Character? character))
return e.SetResult(DataProvider.GetChilds<Property>(character, HierarchyProperties.PropProps));
}
// Create
if (e.Is(DataManagerActionType.Set))
{
if (e.Is(UserType.User) && e.GetObject(out Character? character))
return e.SetResult(CreateProperty(e.CurrentUser, character));
}
}
// PropertyCategory
else if (e.Is(DataManagerActions.Getter.PropertyCategory))
{
// Get
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.User) && e.GetObject(out Character? character))
return e.SetResult(DataProvider.GetChilds<PropertyCategory>(character, HierarchyProperties.PropPropCats));
}
// Create
if (e.Is(DataManagerActionType.Set))
{
if (e.Is(UserType.User) && e.GetObject(out Character? character))
return e.SetResult(CreatePropertyCategory(e.CurrentUser, character));
}
}
return false;
}
protected virtual bool HandleSave(OnActionEventArgs e)
{
if (!e.Is(DataManagerActions.Save))
return false;
if (e.Is(UserType.User) && e.GetObject(out OwnCharObject? obj))
DataProvider.Save(obj);
return false;
}
protected virtual bool HandleDelete(OnActionEventArgs e)
{
if (!e.Is(DataManagerActions.Delete))
return false;
// Character
if (e.GetObject(out Character? character))
return DeleteCharacter(e.CurrentUser, character);
// Group
if (e.GetObject(out Group? group))
return DeleteGroup(e.CurrentUser, group);
// User
if (e.GetObject(out UserAccount? userAccount))
return DeleteUserAccount(userAccount);
// Property
if (e.GetObject(out Property? property))
{
if (e.GetParam(0, out Character? paramChar))
return DeleteIfOwnerOrAdmin(e.CurrentUser, paramChar, property);
}
// Property
if (e.GetObject(out PropertyCategory? propertyCategory))
{
if (e.GetParam(0, out Character? paramChar))
return DeleteIfOwnerOrAdmin(e.CurrentUser, paramChar, propertyCategory);
}
return false;
}
protected virtual bool HandleAssociation(OnActionEventArgs e)
{
if (!e.Is(DataManagerActions.Associate))
return false;
if (e.Is(DataManagerActions.Association.Profile))
{
if (e.GetObject(out UserAccount? account))
{
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.Admin) || (e.Is(UserType.User) && e.CurrentUser == account))
return e.SetResult(DataProvider.GetChild<UserProfile>(account, HierarchyProperties.PropProfile));
}
}
}
else if (e.Is(DataManagerActions.Association.Owner))
{
if (e.GetObject(out Group? group))
{
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.User))
return e.SetResultT(DataProvider.GetChild<UserProfile>(group, HierarchyProperties.PropOwner));
}
else if (e.Is(DataManagerActionType.Set))
{
if (e.Is(UserType.User) && e.GetParam(0, out UserProfile? profile))
return DataProvider.SetChild(group, profile, HierarchyProperties.PropOwner, DataProviderSetAction.Set);
}
}
if (e.GetObject(out Character? character))
{
if (e.Is(DataManagerActionType.Get))
{
if (e.Is(UserType.User))
return e.SetResultT(DataProvider.GetChild<UserProfile>(character, HierarchyProperties.PropOwner));
}
else if (e.Is(DataManagerActionType.Set))
{
if (e.Is(UserType.User) && e.GetParam(0, out UserProfile? profile))
return DataProvider.SetChild(character, profile, HierarchyProperties.PropOwner, DataProviderSetAction.Set);
}
}
}
return false;
}
public IEnumerable<UserProfile>? GetMembers(UserAccount account, Group group)
{
if (!account.HasPermission(UserType.Guest))
return null;
return DataProvider.GetChilds<UserProfile>(group, HierarchyProperties.PropMembers);
}
public UserProfile? GetOwner(UserAccount account, Group group)
{
if (!account.HasPermission(UserType.Guest))
return null;
return DataProvider.GetChild<UserProfile>(group, HierarchyProperties.PropOwner);
}
public UserProfile? GetOwner(UserAccount account, Character character)
{
if (!account.HasPermission(UserType.Guest))
return null;
return DataProvider.GetChild<UserProfile>(character, HierarchyProperties.PropOwner);
}
public UserProfile? GetUserProfile(UserAccount account)
{
ArgumentException.ThrowIfNullOrWhiteSpace(account.Username, nameof(account.Username));
return DataProvider.GetUserProfile(account.Username);
}
public UserAccount? Login(string username, string password)
{
return DataProvider.GetUserAccount(username, password);
}
public bool Logout(UserAccount? account)
{
if (account != null && account.HasPermission(UserType.User))
DataProvider.SaveDatabase();
return true;
}
public bool Initialize(bool force)
{
var result = false;
if (force || !DataProvider.IsInitialized())
{
result = CreateUserAccount(defaultUsername, Utils.HashPassword(defaultUsername, defaultPassword)) != null;
DataProvider.SetInitialized();
}
return result;
}
protected virtual bool DeleteIfOwnerOrAdmin<T>(UserAccount account, Character character, T property) where T : OwnCharObject
{
if (GetUserProfile(account) is not UserProfile profile || DataProvider.GetChild<UserProfile>(character, HierarchyProperties.PropOwner) is not UserProfile owner || !account.HasPermission(profile == owner ? UserType.User : UserType.Admin))
return false;
return DataProvider.Delete(property);
}
protected virtual Property? CreateProperty(UserAccount account, Character character)
{
ArgumentNullException.ThrowIfNull(character, nameof(character));
if (!account.HasPermission(UserType.User))
return null;
var prop = DataProvider.Create<Property>();
ArgumentNullException.ThrowIfNull(prop, nameof(prop));
DataProvider.SetChild(character, prop, HierarchyProperties.PropProps, DataProviderSetAction.Set);
return prop;
}
protected virtual PropertyCategory? CreatePropertyCategory(UserAccount account, Character character)
{
ArgumentNullException.ThrowIfNull(character, nameof(character));
if (!account.HasPermission(UserType.User))
return null;
var cat = DataProvider.Create<PropertyCategory>();
ArgumentNullException.ThrowIfNull(cat, nameof(cat));
DataProvider.SetChild(character, cat, HierarchyProperties.PropPropCats, DataProviderSetAction.Set);
return cat;
}
protected virtual UserAccount? CreateUserAccount(string username, string password)
{
var account = DataProvider.Create<UserAccount>();
var profile = DataProvider.Create<UserProfile>();
var group = DataProvider.Create<Group>();
ArgumentNullException.ThrowIfNull(account, nameof(account));
ArgumentNullException.ThrowIfNull(profile, nameof(profile));
ArgumentNullException.ThrowIfNull(group, nameof(group));
account.Username = username;
account.Password = password;
profile.Name = username;
DataProvider.SetChild(account, profile, HierarchyProperties.PropProfile, DataProviderSetAction.Set);
group.IsInternal = true;
DataProvider.SetChild(group, profile, HierarchyProperties.PropOwner, DataProviderSetAction.Set);
DataProvider.Save(account);
DataProvider.Save(profile);
DataProvider.Save(group);
return account;
}
protected virtual bool DeleteUserAccount(UserAccount account)
{
if (!string.IsNullOrWhiteSpace(account.Username) && DataProvider.GetUserProfile(account.Username) is UserProfile userProfile)
userProfile.Name = "Deleted user";
DataProvider.Delete(account);
return true;
}
protected virtual Group? CreateGroup(UserAccount account, string name)
{
if (!account.HasPermission(UserType.User) || GetUserProfile(account) is not UserProfile profile || DataProvider.Create<Group>() is not Group group)
return null;
group.Name = name;
DataProvider.Save(group);
DataProvider.SetChild(group, profile, HierarchyProperties.PropOwner, DataProviderSetAction.Set);
return group;
}
protected virtual bool DeleteGroup(UserAccount account, Group group)
{
if (GetUserProfile(account) is not UserProfile profile || DataProvider.GetChild<UserProfile>(group, HierarchyProperties.PropOwner) is not UserProfile owner || !account.HasPermission(profile == owner ? UserType.User : UserType.Admin))
return false;
return DataProvider.Delete(group);
}
protected virtual Character? CreateCharacter(UserAccount account, string name, Group? group)
{
if (!account.HasPermission(UserType.User) || GetUserProfile(account) is not UserProfile profile || DataProvider.Create<Character>() is not Character character)
return null;
character.Name = name;
DataProvider.Save(character);
DataProvider.SetChild(character, profile, HierarchyProperties.PropOwner, DataProviderSetAction.Set);
if (group != null)
DataProvider.SetChild(group, character, HierarchyProperties.PropCharacters, DataProviderSetAction.Set);
return character;
}
protected virtual bool DeleteCharacter(UserAccount account, Character character)
{
if (GetUserProfile(account) is not UserProfile profile || DataProvider.GetChild<UserProfile>(character, HierarchyProperties.PropOwner) is not UserProfile owner || !account.HasPermission(profile == owner ? UserType.User : UserType.Admin))
return false;
return DataProvider.Delete(character);
}
}

View File

@@ -1,5 +0,0 @@
namespace OwnChar.Data.Managers;
public class HttpClientDataManager
{
}

View File

@@ -1,14 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data;
public class OnActionEventArgs(DataManagerAction action, DataManagerActionType actionType, UserAccount currentUser, object? obj, object?[] parameters) : EventArgs
{
public DataManagerAction Action { get; } = action;
public DataManagerActionType ActionType { get; } = actionType;
public UserAccount CurrentUser { get; } = currentUser;
public object? Object { get; } = obj;
public object?[] Parameters { get; } = parameters;
public bool IsHandled { get; set; }
public object? Result { get; set; }
}

View File

@@ -1,12 +0,0 @@
using OwnChar.Model;
using System;
namespace OwnChar.Data;
public class OnCallbackEventArgs(DataManagerAction action, DataManagerActionType actionType, bool success, object? result) : EventArgs
{
public DataManagerAction Action { get; } = action;
public DataManagerActionType ActionType { get; } = actionType;
public bool Success { get; } = success;
public object? Result { get; } = result;
}

View File

@@ -1,11 +0,0 @@
using OwnChar.Data.Providers.JsonFile.Model;
namespace OwnChar.Data.Providers.JsonFile;
public class JsonFile
{
public bool IsInitialized { get; set; }
public List<JsonUserAccount> UserAccounts { get; } = [];
public List<JsonCharacter> Characters { get; } = [];
public List<JsonGroup> Groups { get; } = [];
}

View File

@@ -1,457 +0,0 @@
using Newtonsoft.Json;
using OwnChar.Data.Providers.JsonFile.Model;
using OwnChar.Model;
using System.Collections;
using System.Linq;
namespace OwnChar.Data.Providers.JsonFile;
public class JsonFileDataProvider : IDataProvider
{
protected readonly Random random = new();
public JsonFile JsonFile { get; protected set; }
public string JsonFilePath { get; protected set; }
public JsonFileDataProvider(string filePath)
{
JsonFilePath = filePath;
LoadFile();
// Get rid of bad compiler warnings
if (JsonFile == null)
throw new Exception("Something went incredible wrong at initialization of the JsonFile.");
}
protected void LoadFile()
{
if (File.Exists(JsonFilePath) && JsonConvert.DeserializeObject<JsonFile>(File.ReadAllText(JsonFilePath), CreateJsonSerializerSettings()) is JsonFile jsonFile)
JsonFile = jsonFile;
JsonFile ??= new();
}
protected void SaveFile()
{
File.WriteAllText(JsonFilePath, JsonConvert.SerializeObject(JsonFile, CreateJsonSerializerSettings()));
}
protected int GenerateNewObjectId()
{
return random.Next();
}
protected virtual JsonSerializerSettings CreateJsonSerializerSettings()
{
return new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
TypeNameHandling = TypeNameHandling.Auto,
Formatting = Formatting.Indented,
};
}
public bool IsInitialized()
{
return JsonFile.IsInitialized;
}
public void SetInitialized()
{
JsonFile.IsInitialized = true;
}
public bool SaveDatabase()
{
SaveFile();
return true;
}
public T? Create<T>() where T : OwnCharObject
{
var t = typeof(T);
OwnCharObject? obj;
if (t == typeof(Property))
obj = new JsonProp();
else if (t == typeof(PropertyCategory))
obj = new JsonPropCat();
else if (t == typeof(Character))
obj = new JsonCharacter();
else if (t == typeof(Group))
obj = new JsonGroup();
else if (t == typeof(UserAccount))
obj = new JsonUserAccount();
else if (t == typeof(UserProfile))
obj = new JsonUserProfile();
else
obj = null;
if (obj is T objT)
{
objT.Id = GenerateNewObjectId();
return objT;
}
return null;
}
public bool Save<T>(T obj) where T : OwnCharObject
{
if (obj is JsonCharacter character)
{
if (!JsonFile.Characters.Contains(character))
JsonFile.Characters.Add(character);
}
else if (obj is JsonGroup group)
{
if (!JsonFile.Groups.Contains(group))
JsonFile.Groups.Add(group);
}
else if (obj is JsonUserAccount account)
{
if (!JsonFile.UserAccounts.Contains(account))
JsonFile.UserAccounts.Add(account);
}
return true;
}
public bool Delete<T>(T obj) where T : OwnCharObject
{
if (obj is JsonCharacter character)
{
JsonFile.Groups.ForEach(n => n.Characters.Remove(character));
return true;
}
else if (obj is JsonProp prop)
{
JsonFile.Characters.ForEach(n => n.Properties.Remove(prop));
return true;
}
else if (obj is JsonPropCat propCat)
{
JsonFile.Characters.ForEach(n => n.Properties.ForEach(m =>
{
if (m.Category == propCat)
m.Category = null;
}));
JsonFile.Characters.ForEach(n => n.PropertyCategories.Remove(propCat));
return true;
}
else if (obj is JsonGroup group)
{
JsonFile.Groups.Remove(group);
return true;
}
else if (obj is JsonUserAccount account)
{
JsonFile.UserAccounts.Remove(account);
return true;
}
else if (obj is JsonUserProfile profile)
{
// We don't delete profiles at the moment!
profile.Name = "Deleted user";
return true;
}
return false;
}
public IQueryable<T>? GetAll<T>() where T : OwnCharObject
{
var t = typeof(T);
static IQueryable<T>? asList(IEnumerable list) => list.AsQueryable() as IQueryable<T>;
if (t == typeof(Character))
return asList(JsonFile.Characters);
else if (t == typeof(Group))
return asList(JsonFile.Groups);
else if (t == typeof(UserAccount))
return asList(JsonFile.UserAccounts);
return null;
}
public bool SetChild(OwnCharObject parent, OwnCharObject? child, string property, DataProviderSetAction action)
{
// UserAccount
if (parent is JsonUserAccount parentAccount)
{
// User profil
if (property == HierarchyProperties.PropProfile)
{
// Remove
if (child is null || action == DataProviderSetAction.Remove)
{
parentAccount.Profile = null;
return true;
}
// Set
else if (child is JsonUserProfile childProfile)
{
parentAccount.Profile = childProfile;
return true;
}
}
}
// Group
if (parent is JsonGroup parentGroup)
{
// Characters
if (property == HierarchyProperties.PropCharacters)
{
// Clear
if (child is null && action == DataProviderSetAction.Remove)
{
parentGroup.Characters.Clear();
return true;
}
// Add/Remove
else if (child is JsonCharacter childCharacter)
{
// Remove
if (action == DataProviderSetAction.Remove)
{
parentGroup.Characters.Remove(childCharacter);
return true;
}
// Add
else
{
if (!parentGroup.Characters.Contains(childCharacter))
parentGroup.Characters.Add(childCharacter);
return true;
}
}
}
// Members
if (property == HierarchyProperties.PropMembers)
{
// Clear
if (child is null && action == DataProviderSetAction.Remove)
{
parentGroup.Members.Clear();
return true;
}
// Add/Remove
else if (child is JsonUserProfile childProfile)
{
// Remove
if (action == DataProviderSetAction.Remove)
{
parentGroup.Members.Remove(childProfile);
return true;
}
// Add
else
{
if (!parentGroup.Members.Contains(childProfile))
parentGroup.Members.Add(childProfile);
return true;
}
}
}
// Owner
if (property == HierarchyProperties.PropOwner)
{
// Remove
if (child is null || action == DataProviderSetAction.Remove)
{
parentGroup.Owner = null;
return true;
}
// Set
else if (child is JsonUserProfile childProfile)
{
parentGroup.Owner = childProfile;
return true;
}
}
}
// Character
if (parent is JsonCharacter parentCharacter)
{
// Properties
if (property == HierarchyProperties.PropProps)
{
// Clear
if (child is null && action == DataProviderSetAction.Remove)
{
parentCharacter.Properties.Clear();
return true;
}
// Add/Remove
else if (child is JsonProp childProperty)
{
// Remove
if (action == DataProviderSetAction.Remove)
{
parentCharacter.Properties.Remove(childProperty);
return true;
}
// Add
else
{
if (!parentCharacter.Properties.Contains(childProperty))
parentCharacter.Properties.Add(childProperty);
return true;
}
}
}
// Property categories
else if (property == HierarchyProperties.PropPropCats)
{
// Clear
if (child is null && action == DataProviderSetAction.Remove)
{
parentCharacter.PropertyCategories.Clear();
return true;
}
// Add/Remove
else if (child is JsonPropCat childPropertyCategory)
{
// Remove
if (action == DataProviderSetAction.Remove)
{
parentCharacter.PropertyCategories.Remove(childPropertyCategory);
return true;
}
// Add
else
{
if (!parentCharacter.PropertyCategories.Contains(childPropertyCategory))
parentCharacter.PropertyCategories.Add(childPropertyCategory);
return true;
}
}
}
// Owner
else if (property == HierarchyProperties.PropOwner)
{
// Remove
if (child is null || action == DataProviderSetAction.Remove)
{
parentCharacter.Owner = null;
return true;
}
// Set
else if (child is JsonUserProfile childProfile)
{
parentCharacter.Owner = childProfile;
return true;
}
}
}
return false;
}
public T? GetParent<T>(OwnCharObject child, string property) where T : OwnCharObject
{
throw new NotImplementedException("Not yet implemented as not needed.");
}
public T? GetChild<T>(OwnCharObject parent, string property) where T : OwnCharObject
{
// UserAccount
if (parent is JsonUserAccount parentAccount)
{
// User profile
if (property == HierarchyProperties.PropProfile)
return parentAccount.Profile as T;
}
// Group
else if (parent is JsonGroup parentGroup)
{
// Owner
if (property == HierarchyProperties.PropCharacters)
return parentGroup.Owner as T;
}
// Character
else if (parent is JsonCharacter parentCharacter)
{
// Owner
if (property == HierarchyProperties.PropOwner)
return parentCharacter.Owner as T;
}
return null;
}
public IQueryable<T>? GetChilds<T>(OwnCharObject parent, string property) where T : OwnCharObject
{
static IQueryable<T>? asList(IEnumerable list) => list.AsQueryable() as IQueryable<T>;
// Group
if (parent is JsonGroup parentGroup)
{
// Characters
if (property == HierarchyProperties.PropCharacters)
return asList(parentGroup.Characters);
// Members
if (property == HierarchyProperties.PropMembers)
return asList(parentGroup.Members);
}
// Character
else if (parent is JsonCharacter parentCharacter)
{
// Properties
if (property == HierarchyProperties.PropProps)
return asList(parentCharacter.Properties);
// Property categories
if (property == HierarchyProperties.PropPropCats)
return asList(parentCharacter.PropertyCategories);
}
// UserProfile
else if (parent is JsonUserProfile parentUserProfile)
{
// Characters
if (property == HierarchyProperties.PropCharacters)
return asList(JsonFile.Characters.Where(c => c.Owner == parentUserProfile));
// Groups
if (property == HierarchyProperties.PropGroups)
return asList(JsonFile.Groups.Where(g => g.Owner == parentUserProfile));
}
return null;
}
public UserAccount? GetUserAccount(string username, string password)
{
ArgumentException.ThrowIfNullOrWhiteSpace(username, nameof(username));
ArgumentException.ThrowIfNullOrWhiteSpace(password, nameof(password));
return JsonFile.UserAccounts.FirstOrDefault(n => n.Username == username && n.Password == password);
}
public UserProfile? GetUserProfile(string username)
{
return JsonFile.UserAccounts.FirstOrDefault(n => n.Username == username)?.Profile;
}
}

View File

@@ -1,10 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data.Providers.JsonFile.Model;
public class JsonCharacter : Character
{
public virtual JsonUserProfile? Owner { get; set; }
public virtual List<JsonProp> Properties { get; } = [];
public virtual List<JsonPropCat> PropertyCategories { get; } = [];
}

View File

@@ -1,10 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data.Providers.JsonFile.Model;
public class JsonGroup : Group
{
public virtual JsonUserProfile? Owner { get; set; }
public virtual List<JsonUserProfile> Members { get; } = [];
public virtual List<JsonCharacter> Characters { get; } = [];
}

View File

@@ -1,8 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data.Providers.JsonFile.Model;
public class JsonProp : Property
{
public virtual JsonPropCat? Category { get; set; } = null;
}

View File

@@ -1,7 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data.Providers.JsonFile.Model;
public class JsonPropCat : PropertyCategory
{
}

View File

@@ -1,13 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using OwnChar.Model;
namespace OwnChar.Data.Providers.JsonFile.Model;
public class JsonUserAccount : UserAccount
{
public virtual JsonUserProfile? Profile { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public override UserType Type { get => base.Type; set => base.Type = value; }
}

View File

@@ -1,7 +0,0 @@
using OwnChar.Model;
namespace OwnChar.Data.Providers.JsonFile.Model;
public class JsonUserProfile : UserProfile
{
}

View File

@@ -1,6 +0,0 @@
namespace OwnChar.Manager;
public abstract class OwnCharManagerModule(OwnCharManager manager)
{
public OwnCharManager Manager { get; } = manager;
}

View File

@@ -1,8 +1,9 @@
using OwnChar.Api;
using OwnChar.Api.Managers;
using OwnChar.Data;
using OwnChar.Model;
namespace OwnChar.Manager.Modules;
namespace OwnChar.Managers;
public class CharacterManager(OwnCharManager manager) : OwnCharManagerModule(manager), ICharacterManager
{

View File

@@ -1,8 +1,9 @@
using OwnChar.Api;
using OwnChar.Api.Managers;
using OwnChar.Data;
using OwnChar.Model;
namespace OwnChar.Manager.Modules;
namespace OwnChar.Managers;
public class GroupsManager(OwnCharManager manager) : OwnCharManagerModule(manager), IGroupsManager
{

View File

@@ -1,9 +1,10 @@
using OwnChar.Api;
using OwnChar.Api.Managers;
using OwnChar.Data;
using OwnChar.Model;
using Pilz.Cryptography;
namespace OwnChar.Manager.Modules;
namespace OwnChar.Managers;
public class UserManager(OwnCharManager manager) : OwnCharManagerModule(manager), IUserManager
{
@@ -25,7 +26,7 @@ public class UserManager(OwnCharManager manager) : OwnCharManagerModule(manager)
ArgumentException.ThrowIfNullOrWhiteSpace(password, nameof(password));
Manager.CheckLogin();
username = username.Trim().ToLower();
return Manager.DataManager.ExecuteAction(DataManagerActions.Getter.UserAccount, DataManagerActionType.Set, Manager.CurrentUser, null, username, Utils.HashPassword(username, password)).Result as UserAccount;
return Manager.DataManager.ExecuteAction(DataManagerActions.Getter.UserAccount, DataManagerActionType.Set, Manager.CurrentUser, null, username, OwnCharUtils.HashPassword(username, password)).Result as UserAccount;
}
public bool DeleteUserAccount(UserAccount? account)

View File

@@ -2,5 +2,5 @@
public class OwnCharObject
{
public virtual int Id { get; set; }
public virtual long Id { get; set; }
}

View File

@@ -10,8 +10,4 @@
<PackageReference Include="Pilz.Cryptography" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Data\Providers\SqlDb\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
namespace OwnChar;
public class OwnCharApiClient
{
private readonly HttpClient httpClient = new();
}

View File

@@ -4,7 +4,7 @@ using System.Diagnostics.CodeAnalysis;
namespace OwnChar;
public static class Extensions
public static class OwnCharExtensions
{
public static bool GetAt<T>(this object?[] @this, int index, [NotNullWhen(true)] out T? result)
{

View File

@@ -1,12 +1,12 @@
using OwnChar.Api;
using OwnChar.Api.Exceptions;
using OwnChar.Api.Exceptions;
using OwnChar.Api.Managers;
using OwnChar.Data;
using OwnChar.Manager.Modules;
using OwnChar.Model;
using Pilz.Cryptography;
using System.Diagnostics.CodeAnalysis;
namespace OwnChar.Manager;
namespace OwnChar;
public class OwnCharManager : IOwnCharManager
{
@@ -47,7 +47,7 @@ public class OwnCharManager : IOwnCharManager
ArgumentException.ThrowIfNullOrWhiteSpace(password, nameof(password));
username = username.Trim().ToLower();
CurrentUser = proxy.Login(username, Utils.HashPassword(username, password));
CurrentUser = proxy.Login(username, OwnCharUtils.HashPassword(username, password));
DataManager = proxy;
return IsLoggedIn;

View File

@@ -2,7 +2,7 @@
namespace OwnChar;
public static class Utils
public static class OwnCharUtils
{
public static string HashPassword(string username, SecureString password)
{