diff --git a/Gotrue/Api.cs b/Gotrue/Api.cs index 13bad34..229517a 100644 --- a/Gotrue/Api.cs +++ b/Gotrue/Api.cs @@ -575,7 +575,7 @@ public Task DeleteUser(string uid, string jwt) public Task Settings() { - return Helpers.MakeRequest(HttpMethod.Get, $"{Url}/settings"); + return Helpers.MakeRequest(HttpMethod.Get, $"{Url}/settings", null, Headers); } /// diff --git a/Gotrue/Client.cs b/Gotrue/Client.cs index 1cc5bc1..ca5fa91 100644 --- a/Gotrue/Client.cs +++ b/Gotrue/Client.cs @@ -751,7 +751,7 @@ public Session SetAuth(string accessToken) public Func>? GetHeaders { get => _api.GetHeaders; - set => throw new ArgumentException(); + set => _api.GetHeaders = value; } /// @@ -871,5 +871,10 @@ public void LoadSession() if (_sessionPersistence != null) UpdateSession(_sessionPersistence.Persistence.LoadSession()); } + + public Task Settings() + { + return _api.Settings(); + } } } diff --git a/Gotrue/Exceptions/FailureReason.cs b/Gotrue/Exceptions/FailureReason.cs index 8201890..8cb98bb 100644 --- a/Gotrue/Exceptions/FailureReason.cs +++ b/Gotrue/Exceptions/FailureReason.cs @@ -10,10 +10,15 @@ public static class FailureHint public enum Reason { Unknown, + UserEmailNotConfirmed, + UserBadMultiple, UserBadPassword, + UserBadLogin, UserBadEmailAddress, + UserBadPhoneNumber, UserMissingInformation, UserAlreadyRegistered, + UserTooManyRequests, InvalidRefreshToken, AdminTokenRequired } @@ -25,12 +30,23 @@ public static Reason DetectReason(GotrueException gte) return gte.StatusCode switch { + 400 when gte.Content.Contains("Invalid login") => UserBadLogin, + 400 when gte.Content.Contains("Email not confirmed") => UserEmailNotConfirmed, 400 when gte.Content.Contains("User already registered") => UserAlreadyRegistered, 400 when gte.Content.Contains("Invalid Refresh Token") => InvalidRefreshToken, 401 when gte.Content.Contains("This endpoint requires a Bearer token") => AdminTokenRequired, - 422 when gte.Content.Contains("Password should be at least") => UserBadPassword, - 422 when gte.Content.Contains("Unable to validate email address") => UserBadEmailAddress, - 422 when gte.Content.Contains("provide your email or phone number") => UserMissingInformation, + 422 when gte.Content.Contains("Phone") && gte.Content.Contains("Email") => UserBadMultiple, + 422 when gte.Content.Contains("email") && gte.Content.Contains("password") => UserBadMultiple, + 422 when gte.Content.Contains("Phone") => UserBadPhoneNumber, + 422 when gte.Content.Contains("phone") => UserBadPhoneNumber, + 422 when gte.Content.Contains("Phone") => UserBadPhoneNumber, + 422 when gte.Content.Contains("phone") => UserBadPhoneNumber, + 422 when gte.Content.Contains("Email") => UserBadEmailAddress, + 422 when gte.Content.Contains("email") => UserBadEmailAddress, + 422 when gte.Content.Contains("Password") => UserBadPassword, + 422 when gte.Content.Contains("password") => UserBadPassword, + 422 when gte.Content.Contains("provide") => UserMissingInformation, + 429 => UserTooManyRequests, _ => Unknown }; diff --git a/Gotrue/Interfaces/IGotrueClient.cs b/Gotrue/Interfaces/IGotrueClient.cs index 93ef2a4..cd5274d 100644 --- a/Gotrue/Interfaces/IGotrueClient.cs +++ b/Gotrue/Interfaces/IGotrueClient.cs @@ -50,5 +50,8 @@ public interface IGotrueClient : IGettableHeaders Task UpdateUserById(string jwt, string userId, AdminUserAttributes userData); Task VerifyOTP(string phone, string token, MobileOtpType type = MobileOtpType.SMS); Task VerifyOTP(string email, string token, EmailOtpType type = EmailOtpType.MagicLink); + void AddDebugListener(Action logDebug); + void LoadSession(); + Task Settings(); } } \ No newline at end of file diff --git a/Gotrue/Interfaces/IGotrueSessionPersistence.cs b/Gotrue/Interfaces/IGotrueSessionPersistence.cs index e9126a1..7ef06d6 100644 --- a/Gotrue/Interfaces/IGotrueSessionPersistence.cs +++ b/Gotrue/Interfaces/IGotrueSessionPersistence.cs @@ -10,6 +10,6 @@ public interface IGotrueSessionPersistence where TSession : Session public void DestroySession(); - public TSession LoadSession(); + public TSession? LoadSession(); } } diff --git a/Gotrue/Interfaces/IGotrueStatelessClient.cs b/Gotrue/Interfaces/IGotrueStatelessClient.cs index af89c5a..bdcd773 100644 --- a/Gotrue/Interfaces/IGotrueStatelessClient.cs +++ b/Gotrue/Interfaces/IGotrueStatelessClient.cs @@ -32,5 +32,6 @@ public interface IGotrueStatelessClient Task UpdateUserById(string jwt, StatelessClientOptions options, string userId, AdminUserAttributes userData); Task VerifyOTP(string phone, string token, StatelessClientOptions options, MobileOtpType type = MobileOtpType.SMS); Task VerifyOTP(string email, string token, StatelessClientOptions options, EmailOtpType type = EmailOtpType.MagicLink); + Task Settings(StatelessClientOptions options); } } \ No newline at end of file diff --git a/GotrueTests/AnonKeyClientFailureTests.cs b/GotrueTests/AnonKeyClientFailureTests.cs index 1335072..df6b18e 100644 --- a/GotrueTests/AnonKeyClientFailureTests.cs +++ b/GotrueTests/AnonKeyClientFailureTests.cs @@ -18,6 +18,9 @@ namespace GotrueTests [TestClass] public class AnonKeyClientFailureTests { + private readonly List _stateChanges = new List(); + + private IGotrueClient _client; private TestSessionPersistence _persistence; private void AuthStateListener(IGotrueClient sender, Constants.AuthState newState) @@ -43,11 +46,6 @@ public void TestInitializer() _client.AddStateChangedListener(AuthStateListener); } - - private Client _client; - - private readonly List _stateChanges = new List(); - [TestMethod("Client: Sign Up With Bad Password")] public async Task SignUpUserEmailBadPassword() { @@ -85,7 +83,7 @@ public async Task SignUpUserPhone() { await _client.SignUp(Constants.SignUpType.Phone, phone1, PASSWORD, new SignUpOptions { Data = new Dictionary { { "firstName", "Testing" } } }); }); - AreEqual(UserMissingInformation, x.Reason); + AreEqual(UserBadPhoneNumber, x.Reason); IsNull(_persistence.SavedSession); Contains(_stateChanges, SignedOut); AreEqual(1, _stateChanges.Count); @@ -152,7 +150,6 @@ await ThrowsExceptionAsync(async () => IsNotNull(result); }); } - } } diff --git a/GotrueTests/AnonKeyClientTests.cs b/GotrueTests/AnonKeyClientTests.cs index e52c610..3a1c85e 100644 --- a/GotrueTests/AnonKeyClientTests.cs +++ b/GotrueTests/AnonKeyClientTests.cs @@ -18,6 +18,10 @@ namespace GotrueTests public class AnonKeyClientTests { + private readonly List _stateChanges = new List(); + + private IGotrueClient _client; + private TestSessionPersistence _persistence; private void AuthStateListener(IGotrueClient sender, Constants.AuthState newState) @@ -43,10 +47,6 @@ public void TestInitializer() _client.AddStateChangedListener(AuthStateListener); } - private Client _client; - - private readonly List _stateChanges = new List(); - private void VerifyGoodSession(Session session) { Contains(_stateChanges, SignedIn); @@ -89,7 +89,7 @@ public async Task SaveAndLoadUser() var newPersistence = new TestSessionPersistence(); newPersistence.SaveSession(session); - var newClient = new Client(new ClientOptions { AllowUnconfirmedUserSessions = true }); + IGotrueClient newClient = new Client(new ClientOptions { AllowUnconfirmedUserSessions = true }); newClient.SetPersistence(newPersistence); newClient.AddDebugListener(LogDebug); newClient.AddStateChangedListener(AuthStateListener); @@ -331,5 +331,11 @@ public async Task ClientSendsResetPasswordForEmail() var result = await _client.ResetPasswordForEmail(email); IsTrue(result); } + + [TestMethod("Client: Get Settings")] + public async Task Settings() + { + await _client.Settings(); + } } } diff --git a/GotrueTests/ConfigurationFailureTests.cs b/GotrueTests/ConfigurationFailureTests.cs index 0f36382..82bc993 100644 --- a/GotrueTests/ConfigurationFailureTests.cs +++ b/GotrueTests/ConfigurationFailureTests.cs @@ -4,6 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Supabase.Gotrue; using Supabase.Gotrue.Exceptions; +using Supabase.Gotrue.Interfaces; using static GotrueTests.TestUtils; using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert; using static Supabase.Gotrue.Exceptions.FailureHint.Reason; @@ -29,7 +30,7 @@ await ThrowsExceptionAsync(async () => [TestMethod("Bad service key message")] public async Task BadServiceApiKeyTest() { - var client = new Client(new ClientOptions { AllowUnconfirmedUserSessions = true }); + IGotrueClient client = new Client(new ClientOptions { AllowUnconfirmedUserSessions = true }); client.AddDebugListener(LogDebug); var x = await ThrowsExceptionAsync(async () => diff --git a/GotrueTests/ServiceRoleTests.cs b/GotrueTests/ServiceRoleTests.cs index 6a37783..807828b 100644 --- a/GotrueTests/ServiceRoleTests.cs +++ b/GotrueTests/ServiceRoleTests.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Supabase.Gotrue; +using Supabase.Gotrue.Interfaces; using static Supabase.Gotrue.Constants; using static GotrueTests.TestUtils; using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert; @@ -14,7 +15,7 @@ namespace GotrueTests [SuppressMessage("ReSharper", "PossibleNullReferenceException")] public class ServiceRoleTests { - private Client _client; + private IGotrueClient _client; private readonly string _serviceKey = GenerateServiceRoleToken(); diff --git a/GotrueTests/StatelessClientTests.cs b/GotrueTests/StatelessClientTests.cs index 2c4df73..fc9ef86 100644 --- a/GotrueTests/StatelessClientTests.cs +++ b/GotrueTests/StatelessClientTests.cs @@ -9,6 +9,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Supabase.Gotrue; using Supabase.Gotrue.Exceptions; +using Supabase.Gotrue.Interfaces; using static Supabase.Gotrue.StatelessClient; using static Supabase.Gotrue.Constants; @@ -23,6 +24,10 @@ public class StatelessClientTests private static readonly Random Random = new Random(); + private IGotrueStatelessClient _client; + + private static StatelessClientOptions Options { get => new StatelessClientOptions() { AllowUnconfirmedUserSessions = true }; } + private static string RandomString(int length) { const string chars = "abcdefghijklmnopqrstuvwxyz0123456789"; @@ -59,8 +64,6 @@ private string GenerateServiceRoleToken() return tokenHandler.WriteToken(securityToken); } - private StatelessClient _client; - [TestInitialize] public void TestInitializer() @@ -68,8 +71,6 @@ public void TestInitializer() _client = new StatelessClient(); } - private static StatelessClientOptions Options { get => new StatelessClientOptions() { AllowUnconfirmedUserSessions = true }; } - [TestMethod("StatelessClient: Settings")] public async Task Settings() {