James Karet
James Karet

Reputation: 11

Merging more than 2 accounts into one

I have a quite strange or somewhat understandable(?) problem.

My firebase project support 4 types of authentications: Google, Apple, Facebook and anonymous.

I created 2 accounts. One has Google linked with facebook, the other one has apple only. Then I link same facebook account that is already linked with google at apple account.

Firebase console shows no change but everytime I login into apple account, firebase returns google's UID.

I kinda understand that there are all linked into one account but I don't get why the apple's UID isn't removed and google's UID doesn't have apple provider from firebase console.

Another case: Create 3 accounts: Google, Apple and Facebook separately. Link all together into one. every time whichever I login into, firebase returns facebook's UID. (this is something that I completely unable to understand why.)

If it's normal, should I manage them manually on console or my project if I want to see it as one account on firebase console?

Edit: firebase console

Unity FirebaseAuth.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Firebase.Auth;
using System.Text;
using System.Security.Cryptography;
using UnityEngine.SocialPlatforms;
#if !UNITY_IOS
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.OurUtils;
#else
using AppleAuth;
using AppleAuth.Native;
using AppleAuth.Enums;
using AppleAuth.Extensions;
using AppleAuth.Interfaces;
#endif

public class FirebaseAuth : MonoBehaviour
{
    public enum eMOBILEPLATFORM_STATUS
    {
        CONNECTED,
        DISCONNECT,
        ERROR,
        LOGIN_WAIT,
    };

    private static FirebaseAuth _instance;
    protected eMOBILEPLATFORM_STATUS _accountStatus = eMOBILEPLATFORM_STATUS.DISCONNECT;
#if UNITY_IOS
    private IAppleAuthManager _appleAuthManager;
#endif
    public eMOBILEPLATFORM_STATUS Status { get { return _accountStatus; } }
    public FirebaseAuth auth;
    private string _accessToken = string.Empty;


    public static FirebaseAuth Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType(typeof(FirebaseAuth)) as FirebaseAuth;
                if (_instance == null)
                {
                    Debug.LogError("Missing GlobalObject, Use for Firebase");
                    return null;
                }
            }

            return _instance;
        }
    }

    void Update()
    {
#if UNITY_IOS
        if (_appleAuthManager != null) _appleAuthManager.Update();
#endif
    }

    public void Init()
    {
#if !UNITY_IOS
        PlayGamesClientConfiguration config = new PlayGamesClientConfiguration
            .Builder()
            .RequestServerAuthCode(false)
            .RequestIdToken()
            .Build();

        PlayGamesPlatform.InitializeInstance(config);
        PlayGamesPlatform.DebugLogEnabled = true;
        PlayGamesPlatform.Activate();
#else
        if (AppleAuthManager.IsCurrentPlatformSupported)
        {
            var deserializer = new PayloadDeserializer();
            _appleAuthManager = new AppleAuthManager(deserializer);
        }
#endif
        Debug.Log("Firebase Init");
        auth = FirebaseAuth.DefaultInstance;
        _accessToken = string.Empty;
    }
#if !UNITY_IOS
    public void TryGoogleLogin(bool newLogin = true)
    {
        if (!Social.localUser.authenticated)
        {
            Social.localUser.Authenticate(success =>
            {
                if (success)
                {
                    Debug.Log("login success. " + Social.localUser.userName);
                    if (newLogin)
                    {
                        StartCoroutine(TryGoogleFirebaseLogin(newLogin));
                    }
                    else
                    {
                        LinkGoogleFirebase();
                    }
                }
                else
                {
                    Debug.Log("login failed");
                }
            });
        }
        else
        {
            if (newLogin)
            {
                StartCoroutine(TryGoogleFirebaseLogin(newLogin));
            }
            else
            {
                LinkGoogleFirebase();
            }
        }
    }

    public void TryGoogleLogout()
    {
        if (Social.localUser.authenticated)
        {
            PlayGamesPlatform.Instance.SignOut();
            TryFirebaseLogout();
            Debug.Log("logout - done");
        }
    }

    public IEnumerator TryGoogleFirebaseLogin(bool newLogin = true)
    {
        if (newLogin)
        {
            auth.Dispose();
            auth = FirebaseAuth.DefaultInstance;
        }

        while (string.IsNullOrEmpty(((PlayGamesLocalUser)Social.localUser).GetIdToken()))
            yield return null;
        string idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
        _accessToken = idToken;

        Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
        auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("google-CredentialAsync was canceled.");
                return;
            }
            if (task.IsFaulted)
            {
                Debug.LogError("google-CredentialAsync encountered and error: " + task.Exception);
                return;
            }
            Debug.Log("google login success! :D " + auth.CurrentUser.UserId);
            _accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
            UserConfig.Instance.SaveMobilePlatformLogin(true);
            PlayerInfo.Instance.m_bGlobalMobilePlatformLogin = true;
            if (DoesProvierExist("facebook.com"))
            {
                PlayerInfo.Instance.m_bGlobalGuestLogin = false;
                UserConfig.Instance.SaveFacebookLogin(true);
                FacebookManager.Instance.ChangeFacebookStatus(FacebookManager.eFACEBOOK_STATUS.CONNECTED);
            }
        });
    }

    public void LinkGoogleFirebase()
    {
        if (auth != null)
        {
            string idToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken();
            Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
            auth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(task =>
            {
                if (task.IsCanceled)
                {
                    Debug.LogError("google-LinkWithCredentialAsync was canceled.");
                    return;
                }
                if (task.IsFaulted)
                {
                    Debug.LogError("google-LinkWithCredentialAsync encountered an error: " + task.Exception);
                    return;
                }

                FirebaseUser newUser = task.Result;
                Debug.Log("google-Credentials successfully linked to Firebase user: " + newUser.DisplayName + "(" + newUser.UserId + ")");
                _accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
            });
        }
    }
#endif
    public IEnumerator TryFacebookFirebaseLogin(Facebook.Unity.AccessToken accessToken, bool newLogin = false)
    {
        if (newLogin)
        {
            auth = FirebaseAuth.DefaultInstance;
        }

        while (System.String.IsNullOrEmpty(accessToken.TokenString))
            yield return null;

        _accessToken = accessToken.TokenString;

        auth = FirebaseAuth.DefaultInstance;
        Credential credential = FacebookAuthProvider.GetCredential(accessToken.TokenString);
        auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("facebook-CredentialAsync was canceled.");
                return;
            }
            if (task.IsFaulted)
            {
                Debug.LogError("facebook-CredentialAsync encountered and error: " + task.Exception);
                return;
            }
            Debug.Log("facebook firebase success! :D  " + auth.CurrentUser.UserId);
#if !UNITY_IOS
            if(DoesProvierExist("google.com"))
#else
            if(DoesProvierExist("apple.com"))
#endif
            {
                _accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
            }
        });
    }

    public void LinkFacebookFirebase(Facebook.Unity.AccessToken accessToken)
    {
        if (auth != null)
        {
            Credential credential = FacebookAuthProvider.GetCredential(accessToken.TokenString);
            auth.CurrentUser.LinkWithCredentialAsync(credential).ContinueWith(task =>
            {
                if (task.IsCanceled)
                {
                    Debug.LogError("facebook-LinkWithCredentialAsync was canceled.");
                    return;
                }
                if (task.IsFaulted)
                {
                    Debug.LogError("facebook-LinkWithCredentialAsync encountered an error: " + task.Exception);
                    return;
                }

                FirebaseUser newUser = task.Result;
                Debug.Log("facebook-Credentials successfully linked to Firebase user: " + newUser.DisplayName + "(" + newUser.UserId + ")");
                FacebookManager.Instance.ChangeFacebookStatus(FacebookManager.eFACEBOOK_STATUS.CONNECTED);
            });
        }
    }

#if UNITY_IOS
    public IEnumerator TryAppleFirebaseLogin(bool newLogin = true)
    {
        if (newLogin)
        {
            auth.Dispose();
            auth = FirebaseAuth.DefaultInstance;
        }

        string rawNonce = GenerateRandomString(32);
        string nonce = GenerateSHA256NonceFromRawNonce(rawNonce);

        var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName, nonce);

        while (auth==null)
            yield return null;

        _appleAuthManager.LoginWithAppleId(
            loginArgs,
            credential =>
            {
                var appleIdCredential = credential as IAppleIDCredential;
                var identityToken = Encoding.UTF8.GetString(appleIdCredential.IdentityToken);
                var authorizationCode = Encoding.UTF8.GetString(appleIdCredential.AuthorizationCode);
                var firebaseCredential = OAuthProvider.GetCredential("apple.com", identityToken, rawNonce, authorizationCode);

                auth.SignInWithCredentialAsync(firebaseCredential);
                if (appleIdCredential.FullName != null)
                {
                    var userName = appleIdCredential.FullName.ToLocalizedString();

                    var profile = new UserProfile();
                    profile.DisplayName = userName;

                    auth.CurrentUser.UpdateUserProfileAsync(profile);
                }
                _accessToken = authorizationCode.ToString();

                Debug.Log("apple firebase success! :D  " + auth.CurrentUser.UserId);
                _accountStatus = eMOBILEPLATFORM_STATUS.CONNECTED;
                UserConfig.Instance.SaveMobilePlatformLogin(true);
                PlayerInfo.Instance.m_bGlobalMobilePlatformLogin = true;
                if (DoesProvierExist("facebook.com"))
                {
                    PlayerInfo.Instance.m_bGlobalGuestLogin = false;
                    UserConfig.Instance.SaveFacebookLogin(true);
                }
            },
            error =>
            {
                var authorizationErrorCode = error.GetAuthorizationErrorCode();
                switch (authorizationErrorCode)
                {
                    case AuthorizationErrorCode.Canceled:
                        break;
                    case AuthorizationErrorCode.Unknown:
                    case AuthorizationErrorCode.InvalidResponse:
                    case AuthorizationErrorCode.NotHandled:
                    case AuthorizationErrorCode.Failed:
                        Debug.LogError("apple-login failed :/   error code: " + authorizationErrorCode);
                        break;
                }
                return;
            });
    }
#endif
    public IEnumerator TryGuestFirebaseLogin(bool newLogin = false)
    {
        if (newLogin)
        {
            auth.Dispose();
            auth = FirebaseAuth.DefaultInstance;
        }

        while (auth == null)
            yield return null;

        auth.SignInAnonymouslyAsync().ContinueWith(task =>
        {
            if (task.IsCanceled)
            {
                Debug.LogError("guest-SignInAnonymouslyAsync was canceled.");
                return;
            }
            if (task.IsFaulted)
            {
                Debug.LogError("guest-SignInAnonymouslyAsync encountered an error: " + task.Exception);
                return;
            }
            Firebase.Auth.FirebaseUser newUser = task.Result;
            Debug.Log("guest-User signed in successfully :D   " + newUser.DisplayName + " (" + newUser.UserId + ")");
        });
    }

    public void UnlinkFirebase(string providerID)
    {
        if (auth != null && DoesProvierExist(providerID))
        {
            auth.CurrentUser.UnlinkAsync(providerID).ContinueWith(task =>
            {
                if (task.IsCanceled)
                {
                    Debug.LogError(providerID + "-UnlinkAsync was canceled.");
                    return;
                }
                if (task.IsFaulted)
                {
                    Debug.LogError(providerID + "-UnlinkAsync encountered an error: " + task.Exception);
                    return;
                }

                // The user has been unlinked from the provider.
                FirebaseUser newUser = task.Result;
                Debug.LogFormat(providerID + " Credentials successfully unlinked from user: {0} ({1})", newUser.DisplayName, newUser.UserId);
#if !UNITY_IOS
                if (providerID == "google.com")
#else
                if (providerID == "apple.com")
#endif
                {
                    _accountStatus = eMOBILEPLATFORM_STATUS.DISCONNECT;
                }
            });
        }
    }

    public void TryFirebaseLogout()
    {
        auth.SignOut();
    }

    private string GenerateRandomString(int length)
    {
        const string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
        var cryptographicallySecureRandomNumberGenerator = new RNGCryptoServiceProvider();
        var result = string.Empty;
        var remainingLength = length;

        var randomNumberHolder = new byte[1];
        while (remainingLength > 0)
        {
            var randomNumbers = new List<int>(16);
            for (var randomNumberCount = 0; randomNumberCount < 16; randomNumberCount++)
            {
                cryptographicallySecureRandomNumberGenerator.GetBytes(randomNumberHolder);
                randomNumbers.Add(randomNumberHolder[0]);
            }

            for (var randomNumberIndex = 0; randomNumberIndex < randomNumbers.Count; randomNumberIndex++)
            {
                if (remainingLength == 0)
                {
                    break;
                }

                var randomNumber = randomNumbers[randomNumberIndex];
                if (randomNumber < charset.Length)
                {
                    result += charset[randomNumber];
                    remainingLength--;
                }
            }
        }

        return result;
    }

    private string GenerateSHA256NonceFromRawNonce(string rawNonce)
    {
        var sha = new SHA256Managed();
        var utf8RawNonce = Encoding.UTF8.GetBytes(rawNonce);
        var hash = sha.ComputeHash(utf8RawNonce);

        var result = string.Empty;
        for (var i = 0; i < hash.Length; i++)
        {
            result += hash[i].ToString("x2");
        }

        return result;
    }

    public string GetAccessToken()
    {
        return _accessToken;
    }

    /// <summary>
    /// Check the current user has certain provierID.
    /// </summary>
    /// <param name="providerID"> Such as "facebook.com", "apple.com", "google.com"</param>
    /// <returns>false if auth or user is null</returns>
    public bool DoesProvierExist(string providerID)
    {
        FirebaseUser user = auth.CurrentUser;
        bool result = false;
        int checkCount = 0;
        List<string> providers = new List<string>();
        if (user != null)
        {
            foreach (var profile in user.ProviderData)
            {
                checkCount++;
                providers.Add(profile.ProviderId);
                if (profile.ProviderId == providerID)
                    result = true;
            }
        }
#if _USE_DEBUG_LOG_
        string temp = string.Empty;
        for (int i = 0; i < providers.Count; i++)
        {
            temp += providers[i];
            if (i != providers.Count - 1)
                temp += ", ";
        }
        Debug.Log("Just in case if you wanna know. There are " + checkCount + " providerID at this account\n"+temp);
#endif
        return result;
    }
}

and here's xcode log of iphone.

ClickButton (GlobalStart)(04/16/2021 10:22:56)
UIEventButtonClick:OnClick()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

LoginFacebook()False
FacebookManager:LoginFacebook()
UIL_Login:Event_Click(String)
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

2021-04-16 10:22:56.640715+0900 firebaseProject[1006:67274] -canOpenURL: failed for URL: "fbauth2:/" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"
-> applicationWillResignActive()
-> applicationDidBecomeActive()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

2021-04-16 10:22:58.701301+0900 firebaseProject[1006:68330] [tcp] tcp_input [C19.1:3] flags=[R] seq=3046356287, ack=0, win=0 state=CLOSED rcv_nxt=3046356287, snd_una=716434727
2021-04-16 10:22:58.705125+0900 firebaseProject[1006:68330] [tcp] tcp_input [C19.1:3] flags=[R] seq=3046356287, ack=0, win=0 state=CLOSED rcv_nxt=3046356287, snd_una=716434727

CONNECTTING() True
FacebookManager:Connectting()
Facebook.Unity.CallbackManager:TryCallCallback(Object, IResult)
Facebook.Unity.CallbackManager:CallCallback(Object, IResult)
Facebook.Unity.CallbackManager:OnFacebookResponse(IInternalResult)
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

facebook-LinkWithCredentialAsync encountered an error: System.AggregateException: Exception of type 'System.AggregateException' was thrown.
-----------------
Firebase.FirebaseException: [ERROR_PROVIDER_ALREADY_LINKED] - User can only be linked to one identity for the given provider.

System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetException(AggregateException)
System.Threading.Tasks.TaskCompletionSource`1:SetException(Exception)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

2021-04-16 10:23:01.367311+0900 firebaseProject[1006:67777] [tcp] tcp_input [C23.1:3] flags=[R] seq=3109184249, ack=0, win=0 state=CLOSED rcv_nxt=3109184249, snd_una=2797527191
2021-04-16 10:23:01.367444+0900 firebaseProject[1006:67777] [tcp] tcp_input [C23.1:3] flags=[R] seq=3109184249, ack=0, win=0 state=CLOSED rcv_nxt=3109184249, snd_una=2797527191
facebook firebase success! :D  5ThQ■■■■■■■■■■■■■■
<TryFacebookFirebaseLogin>c__Iterator0:<>m__0(Task`1)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Just in case if you wanna know. There are 1 providerID at this account
facebook.com
FirebaseAuth:DoesProvierExist(String)
<TryFacebookFirebaseLogin>c__Iterator0:<>m__0(Task`1)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
System.Threading.Tasks.<ContinueWith>c__AnonStorey0:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey2:<>m__0(Task)
System.Threading.Tasks.<ContinueWith>c__AnonStorey1:<>m__0()
System.Threading.Tasks.Task:<immediateExecutor>m__1(Action)
System.Threading.Tasks.Task`1:RunContinuations()
System.Threading.Tasks.Task`1:TrySetResult(T)
System.Threading.Tasks.TaskCompletionSource`1:SetResult(T)
Firebase.Auth.<GetTask>c__AnonStorey0:<>m__0()
Firebase.Auth.Future_User:SWIG_CompletionDispatcher(Int32)
Firebase.AppUtil:PollCallbacks()
Firebase.Platform.FirebaseHandler:Update()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

ClickButton (LogInBtn)(04/16/2021 10:23:11)
UIEventButtonClick:OnClick()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

firebase apple in
<TryAppleFirebaseLogin>c__Iterator1:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
UIC_OptionPanel:_LinkMobilePlatform(E_MESSAGEBOX_CONFIRM_TYPE)
Messenger`1:Broadcast(String, T, MessengerMode)
UIC_MessageBox_Button:OnClick()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

-> applicationWillResignActive()
-> applicationDidBecomeActive()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

apple firebase success! :D  5ThQ■■■■■■■■■■■■■■
<TryAppleFirebaseLogin>c__AnonStorey3:<>m__0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Just in case if you wanna know. There are 1 providerID at this account
facebook.com
FirebaseAuth:DoesProvierExist(String)
<TryAppleFirebaseLogin>c__AnonStorey3:<>m__0(ICredential)
AppleAuth.CallbackHandler:ExecutePendingCallbacks()
 
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)

Upvotes: 0

Views: 275

Answers (1)

James Karet
James Karet

Reputation: 11

So... I found that lack of knowledge about whatever I'm doing goes very wrong...

I used apple-signin-unity by lupidan from github and mixing various tutorials that I could found on google to expect it's working. :|

Firebase blocks linking multiple accounts that already registered. Mine just dispose previous FirebaseAuth and overwrite new one. that is why it looked like merging accounts that actually doesn't do anything right.

I should have been more careful before I ask question.

Edit: What was actually going on is that there's no exception at apple login. Others have exceptions by using "ContinueWith" function but apple doesn't. by adding it, everything works okay.

Upvotes: 1

Related Questions