diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.gitignore b/.gitignore index 26d814a..add57be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,93 +1,5 @@ -############################################ -# .NET Build -############################################ - -bin/ -obj/ -out/ -publish/ - -############################################ -# Visual Studio -############################################ - -.vs/ -*.user -*.suo -*.userprefs -*.csproj.user -*.dbmdl -*.cache -*.pdb -*.opendb - -############################################ -# Rider / JetBrains -############################################ - -.idea/ -*.sln.iml - -############################################ -# VSCode -############################################ - -.vscode/ - -############################################ -# NuGet -############################################ - -*.nupkg -*.snupkg -packages/ -.nuget/ -.nuget/packages/ - -############################################ -# Logs -############################################ - -*.log -logs/ - -############################################ -# OS files -############################################ - -.DS_Store -Thumbs.db - -############################################ -# Local secrets / environment -############################################ - -.env -.env.* -secrets.json -appsettings.Development.json - -############################################ -# E2EE private keys -############################################ - -keys/* -!keys/.gitkeep - -############################################ -# Local test databases / data folders -############################################ - -data/ -*.db -*.sqlite -*.sqlite3 - -############################################ -# Temporary files -############################################ - -*.tmp -*.temp -*.bak -*.swp \ No newline at end of file +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.RelayCore/.idea/.gitignore b/.idea/.idea.RelayCore/.idea/.gitignore new file mode 100644 index 0000000..50dbf98 --- /dev/null +++ b/.idea/.idea.RelayCore/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/modules.xml +/contentModel.xml +/.idea.RelayCore.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.RelayCore/.idea/AndroidProjectSystem.xml b/.idea/.idea.RelayCore/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..e82600c --- /dev/null +++ b/.idea/.idea.RelayCore/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.RelayCore/.idea/encodings.xml b/.idea/.idea.RelayCore/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.RelayCore/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.RelayCore/.idea/indexLayout.xml b/.idea/.idea.RelayCore/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.RelayCore/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.RelayCore/.idea/vcs.xml b/.idea/.idea.RelayCore/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.RelayCore/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d6dc02a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM mcr.microsoft.com/dotnet/runtime:9.0 AS base +USER $APP_UID +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["RelayCore.csproj", "./"] +RUN dotnet restore "RelayCore.csproj" +COPY . . +WORKDIR "/src/" +RUN dotnet build "./RelayCore.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./RelayCore.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "RelayCore.dll"] diff --git a/RelayCore/PasswordHasher.cs b/PasswordHasher.cs similarity index 97% rename from RelayCore/PasswordHasher.cs rename to PasswordHasher.cs index ee6ed19..d8fbae5 100644 --- a/RelayCore/PasswordHasher.cs +++ b/PasswordHasher.cs @@ -1,109 +1,109 @@ -using System; -using System.Security.Cryptography; -using System.Text; -using Konscious.Security.Cryptography; - -namespace PasswordHasher -{ - /// - /// Provides secure password hashing functionality using Argon2id algorithm - /// - public class PasswordHasher - { - /// - /// Size of the salt in bytes - /// - private const int SaltSize = 16; - - /// - /// Size of the hash in bytes - /// - private const int HashSize = 32; - - /// - /// Number of threads to use for parallel computation - /// - private const int DegreeOfParallelism = 1; - - /// - /// Number of iterations for the Argon2id algorithm - /// - private const int Iterations = 2; - - /// - /// Memory size in KB to use - /// - private const int MemorySize = 19456; // 19 MB - - /// - /// Generates a secure hash of a password using Argon2id with a random salt - /// - /// The plain text password to hash - /// A Base64 string containing the combined salt and hash - /// Thrown when password is null - public string HashPassword(string password) - { - // Generate a random salt - byte[] salt = new byte[SaltSize]; - using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) - { - rng.GetBytes(salt); - } - - // Create hash - byte[] hash = HashPassword(password, salt); - - // Combine salt and hash - var combinedBytes = new byte[salt.Length + hash.Length]; - Array.Copy(salt, 0, combinedBytes, 0, salt.Length); - Array.Copy(hash, 0, combinedBytes, salt.Length, hash.Length); - - // Convert to base64 for storage - return Convert.ToBase64String(combinedBytes); - } - - /// - /// Generates a password hash using Argon2id with a specific salt - /// - /// The plain text password - /// The salt to use for hashing - /// A byte array containing the password hash - private byte[] HashPassword(string password, byte[] salt) - { - var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password)) - { - Salt = salt, - DegreeOfParallelism = DegreeOfParallelism, - Iterations = Iterations, - MemorySize = MemorySize - }; - return argon2.GetBytes(HashSize); - } - - /// - /// Verifies if a password matches a stored hash - /// - /// The plain text password to verify - /// The stored hash in Base64 format - /// True if the password matches the hash, false otherwise - /// Thrown when password or hashedPassword are null - /// Thrown when hashedPassword is not in valid Base64 format - public bool VerifyPassword(string password, string hashedPassword) - { - // Decode the stored hash - byte[] combinedBytes = Convert.FromBase64String(hashedPassword); - - // Extract salt and hash - byte[] salt = new byte[SaltSize]; - byte[] hash = new byte[HashSize]; - Array.Copy(combinedBytes, 0, salt, 0, SaltSize); - Array.Copy(combinedBytes, SaltSize, hash, 0, HashSize); - - // Compute hash for the input password - byte[] newHash = HashPassword(password, salt); - - // Compare the hashes - return CryptographicOperations.FixedTimeEquals(hash, newHash); - } - } +using System; +using System.Security.Cryptography; +using System.Text; +using Konscious.Security.Cryptography; + +namespace PasswordHasher +{ + /// + /// Provides secure password hashing functionality using Argon2id algorithm + /// + public class PasswordHasher + { + /// + /// Size of the salt in bytes + /// + private const int SaltSize = 16; + + /// + /// Size of the hash in bytes + /// + private const int HashSize = 32; + + /// + /// Number of threads to use for parallel computation + /// + private const int DegreeOfParallelism = 1; + + /// + /// Number of iterations for the Argon2id algorithm + /// + private const int Iterations = 2; + + /// + /// Memory size in KB to use + /// + private const int MemorySize = 19456; // 19 MB + + /// + /// Generates a secure hash of a password using Argon2id with a random salt + /// + /// The plain text password to hash + /// A Base64 string containing the combined salt and hash + /// Thrown when password is null + public string HashPassword(string password) + { + // Generate a random salt + byte[] salt = new byte[SaltSize]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(salt); + } + + // Create hash + byte[] hash = HashPassword(password, salt); + + // Combine salt and hash + var combinedBytes = new byte[salt.Length + hash.Length]; + Array.Copy(salt, 0, combinedBytes, 0, salt.Length); + Array.Copy(hash, 0, combinedBytes, salt.Length, hash.Length); + + // Convert to base64 for storage + return Convert.ToBase64String(combinedBytes); + } + + /// + /// Generates a password hash using Argon2id with a specific salt + /// + /// The plain text password + /// The salt to use for hashing + /// A byte array containing the password hash + private byte[] HashPassword(string password, byte[] salt) + { + var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password)) + { + Salt = salt, + DegreeOfParallelism = DegreeOfParallelism, + Iterations = Iterations, + MemorySize = MemorySize + }; + return argon2.GetBytes(HashSize); + } + + /// + /// Verifies if a password matches a stored hash + /// + /// The plain text password to verify + /// The stored hash in Base64 format + /// True if the password matches the hash, false otherwise + /// Thrown when password or hashedPassword are null + /// Thrown when hashedPassword is not in valid Base64 format + public bool VerifyPassword(string password, string hashedPassword) + { + // Decode the stored hash + byte[] combinedBytes = Convert.FromBase64String(hashedPassword); + + // Extract salt and hash + byte[] salt = new byte[SaltSize]; + byte[] hash = new byte[HashSize]; + Array.Copy(combinedBytes, 0, salt, 0, SaltSize); + Array.Copy(combinedBytes, SaltSize, hash, 0, HashSize); + + // Compute hash for the input password + byte[] newHash = HashPassword(password, salt); + + // Compare the hashes + return CryptographicOperations.FixedTimeEquals(hash, newHash); + } + } } \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..33ea9c4 --- /dev/null +++ b/Program.cs @@ -0,0 +1,173 @@ +using System.ComponentModel.Design; +using SurrealDb.Net; +using SurrealDb.Net.Models; +using SurrealDb.Net.Models.Auth; +using System.Text.Json; +using PasswordHasher; + +using var db = new SurrealDbClient("ws://127.0.0.1:8000/rpc"); + +await db.SignIn(new RootAuth { Username = "root", Password = "secret" }); +await db.Use("test", "test"); + +var user = new Users +{ + Username = "Keeper317", + Email = "Keeper317@gmail.com", + CreatedAt = DateTime.Now, + UpdatedAt = DateTime.Now, + LastLogin = DateTime.Now, + TwoFactorEnabled = false, + EmailVerified = false, + AccountStatus = (int) AccountStatuses.Active, + OnlineStatus = (int) OnlineStatuses.Online, +}; +var created = await db.Create("users", user); +Console.WriteLine($"Created Person: {ToJsonString(created)}"); +var hasher = new PasswordHasher.PasswordHasher(); +user.Password = hasher.HashPassword(created.Id + "password"); +user.UpdatedAt = DateTime.Now; +user.LastLogin = DateTime.Now; +user.Id = created.Id; + +bool isValid = hasher.VerifyPassword(created.Id + "password", user.Password); +Console.WriteLine($"Password match: {isValid}"); + +var updated = await db.Merge("users", new() { Id = created.Id, Password = user.Password }); + +// var updated = await db.Merge( +// new() { Id = (TABLE, "8b4nwczy6x8f8zd5sslq"), Marketing = true } +// ); +Console.WriteLine($"Updated Person: {ToJsonString(updated)}"); +// +var people = await db.Select("users"); +Console.WriteLine($"Select Person: {ToJsonString(people)}"); +// +// var queryResponse = await db.Query($"SELECT Marketing, count() AS Count FROM type::table({TABLE}) GROUP BY Marketing"); +// var groups = queryResponse.GetValue>(0); +// Console.WriteLine($"Get Value as group: {ToJsonString(groups)}"); + +await db.Delete("users"); + + +static string ToJsonString(object? o) +{ + return JsonSerializer.Serialize(o, new JsonSerializerOptions { WriteIndented = true, }); +} + +public class ResponsibilityMerge : Record +{ + public bool Marketing { get; set; } +} +public class Group +{ + public bool Marketing { get; set; } + public int Count { get; set; } +} + +public class Users : Record +{ + public required string Username { get; set; } + public string? Password { get; set; } + public required string Email { get; set; } + public required DateTime CreatedAt { get; set; } + public required DateTime UpdatedAt { get; set; } + public required DateTime LastLogin { get; set; } + public bool TwoFactorEnabled { get; set; } + public bool EmailVerified { get; set; } + public required int AccountStatus { get; set; } + public required int OnlineStatus { get; set; } +} + +public class PasswordHash : Record +{ + public string? Password { get; set; } +} + +public class Sessions : Record +{ + public required string UserId { get; set; } + public required string TokenHash { get; set; } + public required DateTime IssuedAt { get; set; } + public required DateTime ExpiresAt { get; set; } + public DateTime? LastUsedAt { get; set; } + public bool Revoked { get; set; } + public required string DeviceName { get; set; } + public required string IpAddress { get; set; } + public required string UserAgent { get; set; } +} + +public class PasswordReset : Record +{ + public required string UserId { get; set; } + public required string TokenHash { get; set; } + public required DateTime CreatedAt { get; set; } + public required DateTime ExpiresAt { get; set; } + public bool Revoked { get; set; } +} + +public class Licenses : Record +{ + public required string UserId { get; set; } + public required int LicenseType { get; set; } + public required int Status { get; set; } + public required DateTime CreatedAt { get; set; } + public required DateTime StartsAt { get; set; } + public required DateTime UpdatedAt { get; set; } + public required DateTime ExpiresAt { get; set; } + +} + +public class AuthAudits : Record +{ + public required string UserId { get; set; } + public required int EventType { get; set; } + public bool Success { get; set; } + public required string IpAddress { get; set; } + public required string UserAgent { get; set; } + public required string Details { get; set; } + public required DateTime CreatedAt { get; set; } +} +enum AccountStatuses +{ + Active, + Suspended, + Banned, + Deleted +} + +enum OnlineStatuses +{ + Online, + Busy, + DND, + Invisible, + Offline +} + +enum LicenseStatuses +{ + Active, + Expired, + Renewable, + Revoked +} + +enum LicenseType +{ + Free, + Basic, + Advanced, + Pro, + Enterprise +} + +enum LogEvents +{ + LoginSuccess, + LoginFailure, + LogoutSuccess, + LogoutFailure, + PasswordResetSuccess, + PasswordResetFailure, +} \ No newline at end of file diff --git a/Relay.sln b/Relay.sln deleted file mode 100644 index c6a098d..0000000 --- a/Relay.sln +++ /dev/null @@ -1,62 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayCore", "RelayCore\RelayCore.csproj", "{346BE501-DE74-4E88-9787-4722FBC8BD0D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayClient", "RelayClient\RelayClient.csproj", "{AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelayServer", "RelayServer\RelayServer.csproj", "{38995780-E9AA-44D6-B62D-07CCA45E4E4C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x64.ActiveCfg = Debug|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x64.Build.0 = Debug|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x86.ActiveCfg = Debug|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Debug|x86.Build.0 = Debug|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|Any CPU.Build.0 = Release|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x64.ActiveCfg = Release|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x64.Build.0 = Release|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x86.ActiveCfg = Release|Any CPU - {346BE501-DE74-4E88-9787-4722FBC8BD0D}.Release|x86.Build.0 = Release|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x64.ActiveCfg = Debug|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x64.Build.0 = Debug|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x86.ActiveCfg = Debug|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Debug|x86.Build.0 = Debug|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|Any CPU.Build.0 = Release|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x64.ActiveCfg = Release|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x64.Build.0 = Release|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x86.ActiveCfg = Release|Any CPU - {AB9DA5AB-55DC-4DE4-834C-E1E1BCD0C3CD}.Release|x86.Build.0 = Release|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x64.ActiveCfg = Debug|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x64.Build.0 = Debug|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x86.ActiveCfg = Debug|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Debug|x86.Build.0 = Debug|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|Any CPU.Build.0 = Release|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x64.ActiveCfg = Release|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x64.Build.0 = Release|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x86.ActiveCfg = Release|Any CPU - {38995780-E9AA-44D6-B62D-07CCA45E4E4C}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/RelayClient/.gitignore b/RelayClient/.gitignore deleted file mode 100644 index 26d814a..0000000 --- a/RelayClient/.gitignore +++ /dev/null @@ -1,93 +0,0 @@ -############################################ -# .NET Build -############################################ - -bin/ -obj/ -out/ -publish/ - -############################################ -# Visual Studio -############################################ - -.vs/ -*.user -*.suo -*.userprefs -*.csproj.user -*.dbmdl -*.cache -*.pdb -*.opendb - -############################################ -# Rider / JetBrains -############################################ - -.idea/ -*.sln.iml - -############################################ -# VSCode -############################################ - -.vscode/ - -############################################ -# NuGet -############################################ - -*.nupkg -*.snupkg -packages/ -.nuget/ -.nuget/packages/ - -############################################ -# Logs -############################################ - -*.log -logs/ - -############################################ -# OS files -############################################ - -.DS_Store -Thumbs.db - -############################################ -# Local secrets / environment -############################################ - -.env -.env.* -secrets.json -appsettings.Development.json - -############################################ -# E2EE private keys -############################################ - -keys/* -!keys/.gitkeep - -############################################ -# Local test databases / data folders -############################################ - -data/ -*.db -*.sqlite -*.sqlite3 - -############################################ -# Temporary files -############################################ - -*.tmp -*.temp -*.bak -*.swp \ No newline at end of file diff --git a/RelayClient/App.xaml b/RelayClient/App.xaml deleted file mode 100644 index 6e6f0eb..0000000 --- a/RelayClient/App.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/RelayClient/App.xaml.cs b/RelayClient/App.xaml.cs deleted file mode 100644 index 895e755..0000000 --- a/RelayClient/App.xaml.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace RelayClient; - -public partial class App : Application -{ - public App() - { - InitializeComponent(); - } - - protected override Window CreateWindow(IActivationState? activationState) - { - return new Window(new AppShell()); - } -} \ No newline at end of file diff --git a/RelayClient/AppShell.xaml b/RelayClient/AppShell.xaml deleted file mode 100644 index e32af14..0000000 --- a/RelayClient/AppShell.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/RelayClient/AppShell.xaml.cs b/RelayClient/AppShell.xaml.cs deleted file mode 100644 index 6c62f2b..0000000 --- a/RelayClient/AppShell.xaml.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace RelayClient; - -public partial class AppShell : Shell -{ - public AppShell() - { - InitializeComponent(); - } -} \ No newline at end of file diff --git a/RelayClient/MainPage.xaml b/RelayClient/MainPage.xaml deleted file mode 100644 index 4f84d78..0000000 --- a/RelayClient/MainPage.xaml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - -