Compare commits
1 Commits
38dc09ab12
...
db5191b0b8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db5191b0b8 |
5
OwnChar/Api/Exceptions/ApiException.cs
Normal file
5
OwnChar/Api/Exceptions/ApiException.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace OwnChar.Api.Exceptions;
|
||||
|
||||
public class ApiException(string message) : Exception(message)
|
||||
{
|
||||
}
|
||||
3
OwnChar/AssemblyInfo.cs
Normal file
3
OwnChar/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("OwnChar.Server")]
|
||||
8
OwnChar/Base/Data/OwnCharRequest.cs
Normal file
8
OwnChar/Base/Data/OwnCharRequest.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Pilz.Cryptography;
|
||||
|
||||
namespace OwnChar.Base.Data;
|
||||
|
||||
public class OwnCharRequest
|
||||
{
|
||||
public SecureString? AuthSecret { get; set; } = null;
|
||||
}
|
||||
11
OwnChar/Base/Data/OwnCharResponse.cs
Normal file
11
OwnChar/Base/Data/OwnCharResponse.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace OwnChar.Base.Data;
|
||||
|
||||
public class OwnCharResponse
|
||||
{
|
||||
[JsonIgnore]
|
||||
public bool IsSuccess => ErrorCode != OwnCharResponseError.None;
|
||||
|
||||
public OwnCharResponseError ErrorCode { get; set; }
|
||||
}
|
||||
8
OwnChar/Base/Data/OwnCharResponseError.cs
Normal file
8
OwnChar/Base/Data/OwnCharResponseError.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace OwnChar.Base.Data;
|
||||
|
||||
public enum OwnCharResponseError
|
||||
{
|
||||
None,
|
||||
Default,
|
||||
NotAuthorized,
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using OwnChar.Client.Data.Model;
|
||||
namespace OwnChar.Base.Data.Requests;
|
||||
|
||||
namespace OwnChar.Base.Data.Requests;
|
||||
|
||||
public class GroupMemberAddRequest
|
||||
public class GroupMemberAddRequest : OwnCharRequest
|
||||
{
|
||||
public Dictionary<long, MemberLevel> Members { get; } = [];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace OwnChar.Base.Data.Requests;
|
||||
|
||||
public class GroupMemberRemoveRequest
|
||||
public class GroupMemberRemoveRequest : OwnCharRequest
|
||||
{
|
||||
public List<long> Members { get; } = [];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace OwnChar.Base.Data.Requests;
|
||||
|
||||
public class LoginRequest(string username, SecureString password)
|
||||
public class LoginRequest(string username, SecureString password) : OwnCharRequest
|
||||
{
|
||||
public string Username { get; } = username;
|
||||
public SecureString Password { get; } = password;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace OwnChar.Base.Data.Requests;
|
||||
|
||||
public class LogoutRequest
|
||||
public class LogoutRequest : OwnCharRequest
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace OwnChar.Base.Data.Requests;
|
||||
|
||||
public class UpdateRequest(OwnCharObjectUpdate update)
|
||||
public class UpdateRequest(OwnCharObjectUpdate update) : OwnCharRequest
|
||||
{
|
||||
public OwnCharObjectUpdate Update { get; } = update;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace OwnChar.Base.Data.Responses;
|
||||
|
||||
public class LoginResponse(UserAccount account, UserProfile profile, string secret)
|
||||
public class LoginResponse(UserAccount? account, UserProfile? profile, string? secret) : OwnCharResponse
|
||||
{
|
||||
public UserAccount Account { get; } = account;
|
||||
public UserProfile Profile { get; } = profile;
|
||||
public UserAccount? Account { get; } = account;
|
||||
public UserProfile? Profile { get; } = profile;
|
||||
public string? Secret { get; } = secret;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace OwnChar.Client.Data.Clients;
|
||||
|
||||
public class CharactersApiClient
|
||||
public class CharactersApiClient(OwnCharApiClient client)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace OwnChar.Client.Data.Clients;
|
||||
|
||||
public class GroupsApiClient
|
||||
public class GroupsApiClient(OwnCharApiClient client)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
namespace OwnChar.Client.Data.Clients;
|
||||
using OwnChar.Base.Data;
|
||||
using OwnChar.Base.Data.Requests;
|
||||
using OwnChar.Base.Data.Responses;
|
||||
using OwnChar.Client.Data.Model;
|
||||
using Pilz.Cryptography;
|
||||
|
||||
public class LoginApiClient
|
||||
namespace OwnChar.Client.Data.Clients;
|
||||
|
||||
public class LoginApiClient(OwnCharApiClient client)
|
||||
{
|
||||
public string Login(string username, string password)
|
||||
public async Task<UserProfile?> Login(string username, SecureString password)
|
||||
{
|
||||
var result = await client.MakeRequest<LoginRequest, LoginResponse>("/auth/login", new(username, password));
|
||||
|
||||
if (!string.IsNullOrEmpty(result.Secret) && result.Profile != null && result.Account != null)
|
||||
{
|
||||
client.AuthSecret = result.Secret;
|
||||
return result.Profile;
|
||||
}
|
||||
|
||||
public string Logout()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<bool> Logout()
|
||||
{
|
||||
await client.MakeRequest<LogoutRequest, OwnCharResponse>("/auth/logout", new());
|
||||
client.AuthSecret = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace OwnChar.Client.Data.Clients;
|
||||
|
||||
public class UsersApiClient
|
||||
public class UsersApiClient(OwnCharApiClient client)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,6 +1,63 @@
|
||||
namespace OwnChar.Client.Data;
|
||||
using OwnChar.Api.Exceptions;
|
||||
using OwnChar.Base.Data;
|
||||
using OwnChar.Client.Data.Clients;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace OwnChar.Client.Data;
|
||||
|
||||
public class OwnCharApiClient
|
||||
{
|
||||
private readonly HttpClient httpClient = new();
|
||||
private readonly Dictionary<Type, object> clients = [];
|
||||
|
||||
internal string? AuthSecret { get; set; } = null;
|
||||
public bool IsLoggedIn => AuthSecret != null;
|
||||
|
||||
public LoginApiClient Auth { get; }
|
||||
public UsersApiClient Users { get; }
|
||||
public CharactersApiClient Characters { get; }
|
||||
public GroupsApiClient Groups { get; }
|
||||
|
||||
public OwnCharApiClient()
|
||||
{
|
||||
Auth = GetClient<LoginApiClient>();
|
||||
Users = GetClient<UsersApiClient>();
|
||||
Characters = GetClient<CharactersApiClient>();
|
||||
Groups = GetClient<GroupsApiClient>();
|
||||
}
|
||||
|
||||
public T GetClient<T>() where T : class
|
||||
{
|
||||
var t = typeof(T);
|
||||
|
||||
if (clients.TryGetValue(t, out var client) && client is T clientT1)
|
||||
return clientT1;
|
||||
|
||||
if (Activator.CreateInstance(t, this) is T clientT2)
|
||||
{
|
||||
clients.Add(t, clientT2);
|
||||
return clientT2;
|
||||
}
|
||||
|
||||
throw new Exception("Client could not be created!");
|
||||
}
|
||||
|
||||
public async Task<TResponse> MakeRequest<TRequest, TResponse>(string requestUrl, TRequest request) where TRequest : OwnCharRequest where TResponse : OwnCharResponse
|
||||
{
|
||||
if (await TryMakeRequest<TRequest, TResponse>(requestUrl, request) is TResponse response)
|
||||
return response;
|
||||
throw new ApiException(string.Format("The api request to \"{0}\" failed!", requestUrl));
|
||||
}
|
||||
|
||||
public async Task<TResponse?> TryMakeRequest<TRequest, TResponse>(string requestUrl, TRequest request) where TRequest : OwnCharRequest where TResponse : OwnCharResponse
|
||||
{
|
||||
request.AuthSecret = AuthSecret;
|
||||
|
||||
var res = await httpClient.PostAsJsonAsync(requestUrl, request);
|
||||
|
||||
if (res.IsSuccessStatusCode)
|
||||
return await res.Content.ReadFromJsonAsync<TResponse>();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
using OwnChar.Client.Managers;
|
||||
using OwnChar.Data;
|
||||
using OwnChar.Model;
|
||||
using OwnChar.Client.Data;
|
||||
using OwnChar.Client.Data.Model;
|
||||
using OwnChar.Client.Managers;
|
||||
using Pilz.Cryptography;
|
||||
|
||||
namespace OwnChar.Client;
|
||||
|
||||
public interface IOwnCharManager
|
||||
{
|
||||
IDataManager? DataManager { get; set; }
|
||||
UserAccountBase? CurrentUser { get; }
|
||||
bool IsLoggedIn { get; }
|
||||
OwnCharApiClient? Api { get; }
|
||||
|
||||
IUserManager Users { get; }
|
||||
IGroupsManager Groups { get; }
|
||||
ICharacterManager Characters { get; }
|
||||
|
||||
bool Login(IDataManager? proxy, string? username, SecureString? password);
|
||||
bool Logout();
|
||||
Task<UserProfile?> Login(string? username, SecureString? password);
|
||||
Task<bool> Logout();
|
||||
|
||||
public static IOwnCharManager CreateDefault()
|
||||
{
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using OwnChar.Api.Exceptions;
|
||||
using OwnChar.Client.Data;
|
||||
using OwnChar.Client.Data.Model;
|
||||
using OwnChar.Client.Managers;
|
||||
using OwnChar.Data;
|
||||
using OwnChar.Manager.Modules;
|
||||
using OwnChar.Model;
|
||||
using Pilz.Cryptography;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
@@ -11,11 +10,10 @@ namespace OwnChar.Client;
|
||||
internal class OwnCharManager : IOwnCharManager
|
||||
{
|
||||
// User
|
||||
public bool IsLoggedIn => CurrentUser != null;
|
||||
public UserAccountBase? CurrentUser { get; private set; }
|
||||
public bool IsLoggedIn => Api is not null && Api.IsLoggedIn;
|
||||
|
||||
// Data Provider
|
||||
public IDataManager? DataManager { get; set; }
|
||||
public OwnCharApiClient? Api { get; private set; }
|
||||
|
||||
// Manager
|
||||
public IUserManager Users { get; }
|
||||
@@ -29,10 +27,10 @@ internal class OwnCharManager : IOwnCharManager
|
||||
Characters = new CharacterManager(this);
|
||||
}
|
||||
|
||||
[MemberNotNull(nameof(CurrentUser), nameof(DataManager))]
|
||||
[MemberNotNull(nameof(Api))]
|
||||
internal protected void CheckLogin()
|
||||
{
|
||||
if (!IsLoggedIn || DataManager == null)
|
||||
if (!IsLoggedIn)
|
||||
throw new LoginException("You are already logged in!");
|
||||
}
|
||||
|
||||
@@ -40,25 +38,25 @@ internal class OwnCharManager : IOwnCharManager
|
||||
/// Tries to login on the given data provider.
|
||||
/// </summary>
|
||||
/// <returns>Returns <see cref="true"/> if the login was successfull and <see cref="false"/> if not.</returns>
|
||||
public bool Login(IDataManager? proxy, string? username, SecureString? password)
|
||||
public Task<UserProfile?> Login(string? username, SecureString? password)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(proxy, nameof(proxy));
|
||||
ArgumentNullException.ThrowIfNull(Api, nameof(Api));
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(username, nameof(username));
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(password, nameof(password));
|
||||
|
||||
username = username.Trim().ToLower();
|
||||
CurrentUser = proxy.Login(username, OwnCharUtils.HashPassword(username, password));
|
||||
DataManager = proxy;
|
||||
|
||||
return IsLoggedIn;
|
||||
return Api.Auth.Login(username, OwnCharUtils.HashPassword(username, password));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the session on the current data provider.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Logout()
|
||||
public async Task<bool> Logout()
|
||||
{
|
||||
return DataManager?.Logout(CurrentUser) ?? true;
|
||||
if (Api is null)
|
||||
return true;
|
||||
return await Api.Auth.Logout();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user