Untitled

 avatar
unknown
csharp
4 days ago
13 kB
14
Indexable
using NetworkBrid;
using Newtonsoft.Json.Linq;
using Save;
using StudioCore;
using System;
using System.Text;
using UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using Utils;

namespace Security
{
    public class Authorization : InitBehaviour, IAuth
    {
        [SerializeField] private AuthStatus authStatus;
        [SerializeField] private string baseUrl;      

        [Header("Login test credentials & testing")]
        public string email;
        public string password;
        public string sceneName;
        public string testResult;

        private string REFRESH_TOKEN_API = "/api/refreshToken";
        private string LOGIN_API = "/api/login";
        private string SCENE_API = "/api/v2/saves/";
        
        private UnityWebRequest activeRequest;

        private IRest Rest;
        private ILoader Loader;
        private ISave Saver;
        private ILoadView LoadView;
        private INetworkUtilsSender UtilsSender;

        [ContextMenu("Simulate login")]
        public void SimulateLogin()
        {
            Login(email, password, (resposne) => LoadInitData(resposne.text, sceneName), (errorCode) => Debug.LogError(errorCode), true);
        }

        public override void Install(IInstalator Installator)
        {
            base.Install(Installator);
            Rest = Installator.Install<IRest>();
            Loader = Installator.Install<ILoader>();
            Saver = Installator.Install<ISave>();
            LoadView = Installator.Install<ILoadView>();
            UtilsSender = Installator.Install<INetworkUtilsSender>();
        }

        public void Login(string email, string password, UnityAction<DownloadHandler> OnLoginSuccesfulled, UnityAction<string> OnLoginFailed, bool loadSceneOnInit)
        {
            Debug.Log($"<color=orange>Begin login attempt</color>");
            JProperty emailProp = new JProperty("email", email);
            JProperty passwordProp = new JProperty("password", password);
            JObject loginData = new JObject(emailProp, passwordProp);
            authStatus.httpOrigin = baseUrl;

            UnityAction<DownloadHandler> LoadInitDataAction = (dh) =>
            {
                LoadInitData(dh.text, sceneName, false);
            };
            OnLoginSuccesfulled += LoadInitDataAction;

            Rest.Request(CustomPostAuthRequest(LOGIN_API, loginData.ToString()), OnLoginSuccesfulled, OnLoginFailed);
        }

        public void Login(string email, string password, UnityAction OnLoginSuccesfulled, UnityAction OnLoginFailed, bool loadSceneOnInit)
        {
            Debug.Log($"<color=orange>Begin login attempt</color>");
            JProperty emailProp = new JProperty("email", email);
            JProperty passwordProp = new JProperty("password", password);
            JObject loginData = new JObject(emailProp, passwordProp);
            authStatus.httpOrigin = baseUrl;

            UnityAction<DownloadHandler> LoadInitDataAction = (dh) =>
            {
                LoadInitData(dh.text, sceneName, false);
            };
            LoadInitDataAction += (dh) => OnLoginSuccesfulled?.Invoke();
            Rest.Request(CustomPostAuthRequest(LOGIN_API, loginData.ToString()), LoadInitDataAction, (str) => OnLoginFailed?.Invoke());
        }

        public void LoadInitData(string loginData, string overrideSaveId = "", bool loadSceneOnInit = true)
        {
            LoadView.DisplayLoad(LoadingType.GameLoading);
            authStatus = JsonUtility.FromJson<AuthStatus>(loginData);

            authStatus.httpOrigin = (authStatus.httpOrigin != null && authStatus.httpOrigin != string.Empty) ? authStatus.httpOrigin : baseUrl;
            Values.GeneralValues.DEFAULT_HTTP_ORIGIN = authStatus.httpOrigin;
            authStatus.saveID = overrideSaveId != string.Empty ? overrideSaveId : authStatus.saveID;

            if (authStatus != null)
            {
                if(loadSceneOnInit)
                {
                    UnityAction<string> OnSceneDataReceived = (data) =>
                    {
                        if (data != string.Empty)
                        {
                            LoadView.HideLoad(LoadingType.GameLoading);
                            Loader.LoadStructure(data);
                            Debug.Log($"<color=green>Succesfull logged int</color>");
                        }
                        else
                        {
                            LoadView.HideLoad(LoadingType.GameLoading);
                            Debug.LogError($"Authorization :: Cannot load authorized load. Cannot parse response into JObject format");
                        }
                    };

                    if(authStatus.saveApiOverride != string.Empty)
                    {
                        GetAuthorizedScene(authStatus.saveID, authStatus.saveApiOverride, OnSceneDataReceived, (errorCode) =>
                        {
                            Debug.LogError($"Cannot get authorized scene. Error code {errorCode}");
                            LoadView.HideLoad(LoadingType.GameLoading);
                        });
                    }
                    else
                    {
                        GetAuthorizedScene(authStatus.saveID, OnSceneDataReceived, (errorCode) =>
                        {
                            Debug.LogError($"Cannot get authorized scene. Error code {errorCode}");
                            LoadView.HideLoad(LoadingType.GameLoading);
                        });
                    }
                    
                }
            }
            else
            {
                LoadView.HideLoad(LoadingType.GameLoading);
                Debug.LogError("Failed to parse initialization data to proper structure");
            }
        }

        public void GetAuthorizedScene(string sceneName, UnityAction<string> OnSuccess, UnityAction<string> OnFailed)
        {
            UnityAction GetAuthorizedScene = () =>
            {
                Rest.Request(CustomGetAuth($"{SCENE_API + sceneName}"), (handler) => OnSuccess?.Invoke(handler.text), OnFailed);
            };

            ValidateToken(GetAuthorizedScene, OnFailed);
        }

        public void GetAuthorizedScene(string sceneName, string saveApiOverride, UnityAction<string> OnSuccess, UnityAction<string> OnFailed)
        {
            UnityAction GetAuthorizedScene = () =>
            {
                Rest.Request(CustomGetAuth($"{saveApiOverride + sceneName}"), (handler) => OnSuccess?.Invoke(handler.text), OnFailed);
            };

            ValidateToken(GetAuthorizedScene, OnFailed);
        }

        public void SaveAuthorizedScene(string sceneName, string scenePayload, UnityAction<string, bool> OnSaveCallback)
        {
            UnityAction SaveAuthorizedScene = () =>
            {
                Rest.Request(CustomPostAuthRequest($"{SCENE_API + sceneName}", scenePayload), (handler) => OnSaveCallback?.Invoke(handler.text, true), (errorCode) => OnSaveCallback?.Invoke(errorCode, false));
            };

            ValidateToken(SaveAuthorizedScene, (error) => Debug.LogError($"Failded to authorize token during scene Save {error}"));
        }

        [ContextMenu("Save Scene")]
        public void SaveAuthorizedScene()
        {
            SaveAuthorizedScene(authStatus.saveID, Saver.SaveOb().ToString(), (payload, success) => { });
        }

        public void ValidateToken(UnityAction OnTokenValidated, UnityAction<string> OnTokenValidationFailed)
        {
            long currentSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            bool dateIsValid = authStatus.accessTokenExpirationTime > currentSeconds;
            if (dateIsValid)
            {
                OnTokenValidated?.Invoke();
            }
            else
            {
                Debug.Log("<color=red> Token is no longer valid. Attemp to refresh it</color>");

                JProperty emailProp = new JProperty("email", authStatus.user.email);
                JProperty refreshProp = new JProperty("refreshToken", authStatus.refreshToken);
                JObject loginData = new JObject(emailProp, refreshProp);

                UnityAction<DownloadHandler> OnTokenSuccesfullRefresh = (refreshedToken) =>
                {
                    TokenRefreshModel refresh = JsonUtility.FromJson<TokenRefreshModel>(refreshedToken.text);
                    if (refresh == null)
                    {
                        OnTokenValidationFailed?.Invoke($"Received refresh data but it's corrupted. Cannop parse into TokenModel. Data -> {refreshedToken}");
                        UtilsSender.LogoutImmidiately();
                        return;
                    }

                    authStatus.accessToken = refresh.accessToken;
                    authStatus.refreshToken = refresh.refreshToken;

                    authStatus.accessTokenExpirationTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + refresh.expiresIn;
                    OnTokenValidated?.Invoke();
                    Debug.Log("<color=green> Token succesfully refreshed</color>");
                };

                UnityAction<string> OnTokenRefreshFailed = (errorCode) =>
                {
                    OnTokenValidationFailed?.Invoke($"Error: {errorCode}. Token refresh was unsuccesfull. Clearing up the data");
                    authStatus = null;
                    UtilsSender.LogoutImmidiately();
                };

                Rest.Request(CustomPostAuthRequest(REFRESH_TOKEN_API, loginData.ToString()), OnTokenSuccesfullRefresh, OnTokenRefreshFailed);
            }
        }

        [ContextMenu("Validate Token")]
        public void TestTokenValidation()
        {
            ValidateToken(() => Debug.Log("TokenValid"), (errorCode) => Debug.Log($"Token validation failed with code {errorCode}"));
        }

        [ContextMenu("Text Get Scene")]
        public void GetScene()
        {
            GetAuthorizedScene(sceneName, (data) =>
            {
                JObject parsed = JObject.Parse(data);

                foreach (var prop in parsed.Properties())
                {                    
                    testResult = prop.Value.ToString();
                }
            
            }, (errorCode) => Debug.Log(errorCode));
        }

        public UnityWebRequest CustomPostAuthRequest(string apiKey, string data)
        {
            var request = new UnityWebRequest(authStatus.httpOrigin + apiKey, "POST");
            byte[] bodyRaw = Encoding.UTF8.GetBytes(data.ToString());
            request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
            request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            request.SetRequestHeader("Content-Type", @"application/json");
            request.SetRequestHeader("Authorization", $"bearer {authStatus.accessToken}");
            activeRequest = request;
            return request;
        }

        public UnityWebRequest CustomGetAuth(string apiKey)
        {
            var request = new UnityWebRequest(authStatus.httpOrigin + apiKey, "GET");
            request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            request.SetRequestHeader("Accept", $"application/json");
            request.SetRequestHeader("Content-Type", @"application/json");
            request.SetRequestHeader("Authorization", $"bearer {authStatus.accessToken}");
            activeRequest = request;
            return request;
        }

        public void Logout()
        {
            authStatus = new AuthStatus();
        }
        
        private void OnDisable()
        {
            StopAllCoroutines();
        }
        
        private void OnDestroy()
        {
            if (activeRequest != null)
            {
                activeRequest.Abort();
                activeRequest.Dispose();
                activeRequest = null;
            }
        }

    }

    #region Models
    [Serializable]
    public class AuthStatus
    {
        public string accessToken = string.Empty;
        public string refreshToken = string.Empty;
        public int expiresIn;
        public long accessTokenExpirationTime;
        public UserAuthStatus user;
        public string saveID = string.Empty;
        public string httpOrigin = string.Empty;
        public string saveApiOverride = string.Empty;

        [Serializable]
        public class UserAuthStatus
        {
            public string email;
        }
    }

    [Serializable]
    public class TokenRefreshModel
    {
        public string accessToken = string.Empty;
        public int expiresIn;
        public string refreshToken = string.Empty;
    }
    #endregion
}
Editor is loading...
Leave a Comment