Ver Fonte

Added api key

Krzysztof Krysiński há 3 semanas atrás
pai
commit
287cc48453

+ 20 - 11
src/PixiEditor.IdentityProvider.PixiAuth/PixiAuthIdentityProvider.cs

@@ -1,4 +1,5 @@
-using Avalonia.Threading;
+using System.Security.Cryptography.X509Certificates;
+using Avalonia.Threading;
 using PixiEditor.OperatingSystem;
 using PixiEditor.PixiAuth;
 using PixiEditor.PixiAuth.Exceptions;
@@ -10,8 +11,8 @@ public class PixiAuthIdentityProvider : IIdentityProvider
 {
     public string ProviderName { get; } = "PixiAuth";
     public bool AllowsLogout { get; } = true;
-    public bool ApiValid => apiValid;
-    private bool apiValid = true;
+    public bool IsValid => isValid;
+    private bool isValid = true;
     public PixiAuthClient PixiAuthClient { get; }
     public PixiUser User { get; private set; }
     public bool IsLoggedIn => User?.IsLoggedIn ?? false;
@@ -27,16 +28,16 @@ public class PixiAuthIdentityProvider : IIdentityProvider
 
     IUser IIdentityProvider.User => User;
 
-    public PixiAuthIdentityProvider(string pixiEditorApiUrl)
+    public PixiAuthIdentityProvider(string pixiEditorApiUrl, string? apiKey)
     {
         try
         {
-            PixiAuthClient = new PixiAuthClient(pixiEditorApiUrl);
+            PixiAuthClient = new PixiAuthClient(pixiEditorApiUrl, apiKey);
         }
         catch (UriFormatException e)
         {
             Console.WriteLine($"Invalid api URL format: {e.Message}");
-            apiValid = false;
+            isValid = false;
         }
     }
 
@@ -55,7 +56,7 @@ public class PixiAuthIdentityProvider : IIdentityProvider
 
     public async Task RequestLogin(string email)
     {
-        if (!apiValid) return;
+        if (!isValid) return;
 
         try
         {
@@ -91,11 +92,19 @@ public class PixiAuthIdentityProvider : IIdentityProvider
             Error(tooManyRequestsException.Message, tooManyRequestsException.TimeLeft);
             LoginTimeout?.Invoke(tooManyRequestsException.TimeLeft);
         }
+        catch(UnauthorizedAccessException unauthorizedAccessException)
+        {
+            Error("UNAUTHORIZED_ACCESS", unauthorizedAccessException.Message);
+        }
+        catch (Exception e)
+        {
+            Error("INTERNAL_SERVER_ERROR", e);
+        }
     }
 
     public async Task ResendActivation(string email)
     {
-        if (!apiValid) return;
+        if (!isValid) return;
 
         string emailHash = EmailUtility.GetEmailHash(email);
         if (User?.EmailHash != emailHash)
@@ -135,7 +144,7 @@ public class PixiAuthIdentityProvider : IIdentityProvider
 
     public async Task<bool> TryRefreshToken()
     {
-        if (!apiValid) return false;
+        if (!isValid) return false;
 
         if (!IsLoggedIn)
         {
@@ -196,7 +205,7 @@ public class PixiAuthIdentityProvider : IIdentityProvider
         LoggedOut?.Invoke();
         SaveUserInfo();
 
-        if (!apiValid) return;
+        if (!isValid) return;
 
         try
         {
@@ -249,7 +258,7 @@ public class PixiAuthIdentityProvider : IIdentityProvider
 
     public async Task<bool> TryValidateSession()
     {
-        if (!apiValid) return false;
+        if (!isValid) return false;
 
         if (User?.SessionId == null)
         {

+ 1 - 0
src/PixiEditor.IdentityProvider/IIdentityProvider.cs

@@ -7,6 +7,7 @@ public interface IIdentityProvider
     public IUser User { get; }
     public bool IsLoggedIn { get; }
     public Uri? EditProfileUrl { get; }
+    public bool IsValid { get; }
 
     public event Action<string, object> OnError;
     public event Action<List<ProductData>> OwnedProductsUpdated;

+ 29 - 2
src/PixiEditor.PixiAuth/PixiAuthClient.cs

@@ -11,13 +11,16 @@ public class PixiAuthClient
 {
     private HttpClient httpClient;
 
-    public string BaseUrl { get; }
 
-    public PixiAuthClient(string baseUrl)
+    public PixiAuthClient(string baseUrl, string? apiKey)
     {
         httpClient = new HttpClient();
         httpClient.BaseAddress = new Uri(baseUrl);
         httpClient.Timeout = TimeSpan.FromSeconds(30);
+        if (apiKey != null)
+        {
+            httpClient.DefaultRequestHeaders.Add("X-API-KEY", apiKey);
+        }
     }
 
     public async Task<Guid?> GenerateSession(string email)
@@ -57,6 +60,14 @@ public class PixiAuthClient
                 }
             }
         }
+        else if (response.StatusCode == HttpStatusCode.Unauthorized)
+        {
+            throw new UnauthorizedAccessException("UNAUTHORIZED");
+        }
+        else if (response.StatusCode == HttpStatusCode.Forbidden)
+        {
+            throw new ForbiddenException("FORBIDDEN");
+        }
 
         return null;
     }
@@ -94,6 +105,14 @@ public class PixiAuthClient
         {
             throw new InternalServerErrorException("INTERNAL_SERVER_ERROR");
         }
+        else if (response.StatusCode == HttpStatusCode.Unauthorized)
+        {
+            throw new UnauthorizedAccessException("UNAUTHORIZED");
+        }
+        else if (response.StatusCode == HttpStatusCode.Forbidden)
+        {
+            throw new ForbiddenException("FORBIDDEN");
+        }
 
         return (null, null);
     }
@@ -150,6 +169,14 @@ public class PixiAuthClient
         {
             throw new InternalServerErrorException("INTERNAL_SERVER_ERROR");
         }
+        else if (response.StatusCode == HttpStatusCode.Unauthorized)
+        {
+            throw new UnauthorizedAccessException("UNAUTHORIZED");
+        }
+        else if (response.StatusCode == HttpStatusCode.Forbidden)
+        {
+            throw new ForbiddenException("FORBIDDEN");
+        }
 
         return (null, null);
     }

+ 1 - 1
src/PixiEditor.Platform.MSStore/MSAdditionalContentProvider.cs

@@ -24,7 +24,7 @@ public sealed class MSAdditionalContentProvider : IAdditionalContentProvider
 
     public async Task<string?> InstallContent(string productId)
     {
-        if (!IdentityProvider.ApiValid) return null;
+        if (!IdentityProvider.IsValid) return null;
 
         if (IdentityProvider.User is not { IsLoggedIn: true })
         {

+ 1 - 1
src/PixiEditor.Platform.Standalone/StandaloneAdditionalContentProvider.cs

@@ -22,7 +22,7 @@ public sealed class StandaloneAdditionalContentProvider : IAdditionalContentProv
 
     public async Task<string?> InstallContent(string productId)
     {
-        if (!IdentityProvider.ApiValid) return null;
+        if (!IdentityProvider.IsValid) return null;
 
         if (IdentityProvider.User is not { IsLoggedIn: true })
         {

+ 2 - 2
src/PixiEditor.Platform.Standalone/StandalonePlatform.cs

@@ -12,9 +12,9 @@ public sealed class StandalonePlatform : IPlatform
     public IIdentityProvider? IdentityProvider { get; }
     public IAdditionalContentProvider? AdditionalContentProvider { get; }
 
-    public StandalonePlatform(string extensionsPath, string apiUrl)
+    public StandalonePlatform(string extensionsPath, string apiUrl, string? apiKey)
     {
-        PixiAuthIdentityProvider authProvider = new PixiAuthIdentityProvider(apiUrl);
+        PixiAuthIdentityProvider authProvider = new PixiAuthIdentityProvider(apiUrl, apiKey);
         IdentityProvider = authProvider;
         AdditionalContentProvider = new StandaloneAdditionalContentProvider(extensionsPath, authProvider);
     }

+ 1 - 0
src/PixiEditor.Platform.Steam/SteamIdentityProvider.cs

@@ -12,6 +12,7 @@ public class SteamIdentityProvider : IIdentityProvider
     public IUser User { get; private set; }
     public bool IsLoggedIn { get; private set; }
     public Uri? EditProfileUrl { get; } = new Uri("https://store.steampowered.com/login/");
+    public bool IsValid => true;
     public event Action<string, object>? OnError;
     public event Action<List<ProductData>>? OwnedProductsUpdated;
     public event Action<string>? UsernameUpdated;

+ 2 - 0
src/PixiEditor/BuildConstants.cs

@@ -7,4 +7,6 @@ public static class BuildConstants
     public const string AnalyticsUrl = "${analytics-url}";
 
     public const string PixiEditorApiUrl = "${api-url}";
+
+    public const string? PixiEditorApiKey = "${api-key}";
 }

+ 2 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -1121,5 +1121,6 @@
   "COMPOSE_MATRIX": "Compose Matrix",
   "DECOMPOSE_MATRIX": "Decompose Matrix",
   "NORMALIZE_COORDINATES": "Normalize Coordinates",
-  "TRANSFORMED_POSITION": "Transformed Position"
+  "TRANSFORMED_POSITION": "Transformed Position",
+  "ACCOUNT_PROVIDER_NOT_AVAILABLE": "This build of PixiEditor does not support accounts. Use the official build from pixieditor.net to manage your account."
 }

+ 19 - 1
src/PixiEditor/Initialization/ClassicDesktopEntry.cs

@@ -173,7 +173,8 @@ internal class ClassicDesktopEntry
 #elif MSIX || MSIX_DEBUG
         return new PixiEditor.Platform.MSStore.MicrosoftStorePlatform();
 #else
-        return new PixiEditor.Platform.Standalone.StandalonePlatform(Paths.LocalExtensionPackagesPath, GetApiUrl());
+        return new PixiEditor.Platform.Standalone.StandalonePlatform(Paths.LocalExtensionPackagesPath, GetApiUrl(),
+            GetApiKey());
 #endif
     }
 
@@ -290,4 +291,21 @@ internal class ClassicDesktopEntry
 
         return baseUrl;
     }
+
+    private string GetApiKey()
+    {
+        string? apiKey = BuildConstants.PixiEditorApiKey;
+#if DEBUG
+        if (apiKey != null && apiKey.Contains('{') && apiKey.Contains('}'))
+        {
+            string? envApiKey = Environment.GetEnvironmentVariable("PIXIEDITOR_API_KEY");
+            if (envApiKey != null)
+            {
+                apiKey = envApiKey;
+            }
+        }
+#endif
+
+        return apiKey;
+    }
 }

+ 8 - 1
src/PixiEditor/Views/Auth/LoginPopup.axaml

@@ -18,5 +18,12 @@
         <subViewModels:UserViewModel />
     </Design.DataContext>
 
-    <auth:LoginForm Margin="15" DataContext="{Binding}" />
+    <Panel>
+        <auth:LoginForm
+            IsVisible="{Binding DataContext.IdentityProvider.IsValid, RelativeSource={RelativeSource AncestorType=auth:LoginPopup, Mode=FindAncestor}}"
+            Margin="15" DataContext="{Binding}" />
+        <TextBlock IsVisible="{Binding !DataContext.IdentityProvider.IsValid, RelativeSource={RelativeSource AncestorType=auth:LoginPopup, Mode=FindAncestor}}"
+                   Text="{localization:Translate Key=ACCOUNT_PROVIDER_NOT_AVAILABLE}"
+                   Margin="15" TextWrapping="Wrap" />
+    </Panel>
 </dialogs:PixiEditorPopup>