Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 228 additions & 0 deletions Runtime/Editor/Editor UI/LootLockerAdminExtension.Authentication.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
using System;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;

#if UNITY_EDITOR && UNITY_2021_3_OR_NEWER && !LOOTLOCKER_DISABLE_EDITOR_EXTENSION
using LootLocker.Extension.Responses;

namespace LootLocker.Extension
{
public partial class LootLockerAdminExtension : EditorWindow
{
public void Login()
{
if (string.IsNullOrEmpty(emailField?.value) || string.IsNullOrEmpty(passwordField?.value))
{
ShowPopup("Error", "Email or Password is empty.");
HideLoading();
return;
}

ShowLoadingAndExecute(() =>
{
try
{
LootLockerAdminManager.AdminLogin(emailField.value, passwordField.value, OnLoginComplete);
}
catch (Exception ex)
{
ShowPopup("Error", $"Unexpected error: {ex.Message}");
HideLoading();
}
});
}

private void OnLoginComplete(LoginResponse response)
{
if (!response.success)
{
string errorMsg = !string.IsNullOrEmpty(response.errorData?.message)
? response.errorData.message
: "We couldn't recognize your information or there is no user with this email, please check and try again!";
ShowPopup("Error", errorMsg);
HideLoading();
return;
}

if (response.mfa_key != null)
{
mfaKey = response.mfa_key;
if (menu != null) menu.style.display = DisplayStyle.Flex;
HideLoading();
SwapFlows(mfaFlow);
}
else
{
CompleteLogin(response.auth_token);
}

if (menuLogoutBtn != null) menuLogoutBtn.style.display = DisplayStyle.Flex;
}

private void CompleteLogin(string authToken)
{
if (menu != null) menu.style.display = DisplayStyle.Flex;
LootLockerConfig.current.adminToken = authToken;
LootLockerEditorData.SetAdminToken(authToken);
HideLoading();
SwapFlows(gameSelectorFlow);
}

public void SignIn(EventBase e)
{
ShowLoadingAndExecute(() =>
{
LootLockerAdminManager.MFAAuthenticate(mfaKey, codeField.value, (onComplete) =>
{
if (!onComplete.success)
{
ShowPopup("Error", "Could not authenticate MFA!");
HideLoading();
return;
}

CompleteLogin(onComplete.auth_token);
SwapFlows(gameSelectorFlow);
});
});
}

public void RefreshUserInformation(Action onComplete)
{
ShowLoadingAndExecute(() =>
{
LootLockerAdminManager.GetUserInformation((response) =>
{
if (!response.success)
{
ShowPopup("Error", "Your token has expired, will redirect you to Login page now!");
Debug.Log(response.errorData.message);
HideLoading();
Logout();
return;
}

ProcessUserInformation(response);
UpdateLicenseCountdownUI();
gameDataRefreshTime = DateTime.Now;
onComplete?.Invoke();
HideLoading();
});
});
}

private void ProcessUserInformation(LoginResponse response)
{
gameData.Clear();

foreach (var org in response.user.organisations)
{
foreach (var game in org.games)
{
if (game.id == LootLockerEditorData.GetSelectedGame() || game.development.id == LootLockerEditorData.GetSelectedGame())
{
LootLockerEditorData.SetSelectedGameName(game.name);
}
game.organisation_name = org.name;
gameData.Add(game.id, game);
}
}
}

void CreateNewAPIKey()
{
int gameId = LootLockerEditorData.GetSelectedGame();
if (gameId == 0)
{
ShowPopup("Error", "No active Game found!");
return;
}

if (isStage && gameData.ContainsKey(gameId))
{
gameId = gameData[gameId].development.id;
}

ShowLoadingAndExecute(() =>
{
LootLockerAdminManager.GenerateKey(gameId, newApiKeyName.value, "game", (onComplete) =>
{
if (!onComplete.success)
{
ShowPopup("Error", "Could not create a new API Key!");
HideLoading();
return;
}

APIKeyTemplate(onComplete);
HideLoading();
});
});

if (newApiKeyName != null) newApiKeyName.value = "";
}

public void RefreshAPIKeys()
{
if (apiKeyList != null) apiKeyList.Clear();

int gameID = LootLockerEditorData.GetSelectedGame();
if (isStage && gameData.ContainsKey(gameID))
{
gameID = gameData[gameID].development.id;
}

isLoadingKeys = true;

ShowLoadingAndExecute(() =>
{
LootLockerAdminManager.GetAllKeys(gameID, (onComplete) =>
{
if (!onComplete.success)
{
ShowPopup("Error", "Could not find API Keys!");
HideLoading();
return;
}

foreach (var key in onComplete.api_keys)
{
APIKeyTemplate(key);
}

isLoadingKeys = false;
HideLoading();
});
});
}

void ConfirmLogout()
{
ShowPopup("Confirm Logout", "Are you sure you want to log out? This will clear your admin token and settings.");
if (popupBtn != null)
{
popupBtn.clickable.clickedWithEventInfo -= ClosePopup;
popupBtn.clickable.clickedWithEventInfo += (evt) =>
{
Logout();
ClosePopup(evt);
};
}
}

void Logout()
{
if (loadingPage != null) loadingPage.style.display = DisplayStyle.Flex;
LootLockerEditorData.ClearLootLockerPrefs();

gameData.Clear();
if (apiKeyList != null) apiKeyList.Clear();
if (gameSelectorList != null) gameSelectorList.Clear();

if (loadingPage != null) loadingPage.style.display = DisplayStyle.None;
SwapFlows(loginFlow);
}
}
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

154 changes: 154 additions & 0 deletions Runtime/Editor/Editor UI/LootLockerAdminExtension.EventHandlers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;

#if UNITY_EDITOR && UNITY_2021_3_OR_NEWER && !LOOTLOCKER_DISABLE_EDITOR_EXTENSION
namespace LootLocker.Extension
{
public partial class LootLockerAdminExtension : EditorWindow
{
// Event handlers for UI interactions
private void OnPasswordKeyDown(KeyDownEvent evt)
{
if (evt.keyCode == KeyCode.Return)
{
Login();
}
}

private void OnNewApiKeyCancelClick(MouseDownEvent evt)
{
if (newApiKeyName != null) newApiKeyName.value = "";
if (newApiKeyWindow != null) newApiKeyWindow.style.display = DisplayStyle.None;
}

private void OnCreateApiKeyClick()
{
CreateNewAPIKey();
if (newApiKeyWindow != null) newApiKeyWindow.style.display = DisplayStyle.None;
}

private void OnCreateNewApiKeyClick()
{
if (newApiKeyWindow != null) newApiKeyWindow.style.display = DisplayStyle.Flex;
}

private void OnSettingsClick()
{
previousFlow = currentFlow;
RequestFlowSwitch(settingsFlow, LoadSettingsUI);
}

private void OnSettingsBackClick()
{
if (previousFlow != null)
{
RequestFlowSwitch(previousFlow);
previousFlow = null;
}
else
{
RequestFlowSwitch(apiKeyFlow);
}
}

private void OnGameSelected(EventBase e)
{
if (!AtTarget(e)) return;

var target = e.target as Button;
if (target == null) return;

LootLockerEditorData.SetSelectedGame(target.name);
var selectedGameData = gameData[int.Parse(target.name)];

LootLockerEditorData.SetSelectedGameName(selectedGameData.name);
gameName.text = selectedGameData.name;
UpdateLicenseCountdownUI();

LootLockerEditorData.SetEnvironmentStage();
isStage = true;

ShowLoadingAndExecute(() =>
{
LootLockerAdminManager.GetGameDomainKey(LootLockerEditorData.GetSelectedGame(), (onComplete) =>
{
HideLoading();
if (!onComplete.success)
{
ShowPopup("Error", "Could not find Selected game!");
return;
}
LootLockerConfig.current.domainKey = onComplete.game.domain_key;
});
});

SwapFlows(apiKeyFlow);
}

private void OnAPIKeySelected(EventBase e)
{
if (!AtTarget(e)) return;

var target = e.target as Button;
if (target == null) return;

LootLockerConfig.current.apiKey = target.name;
SwapNewSelectedKey();
ShowPopup("API Key Selected", $"API Key {target.name} is now active.");
}

private void LicenseCountdownIconClick(MouseDownEvent evt)
{
Application.OpenURL("https://console.lootlocker.com");
evt.StopPropagation();
}

private void LicenseCountdownContainerClick(MouseDownEvent evt)
{
Application.OpenURL("https://console.lootlocker.com");
evt.StopPropagation();
}

private bool AtTarget(EventBase eventBase)
{
#if UNITY_2023_1_OR_NEWER
return eventBase.propagationPhase == PropagationPhase.BubbleUp;
#else
return eventBase.propagationPhase == PropagationPhase.AtTarget;
#endif
}

private void OnEditorUpdate()
{
EditorApplication.QueuePlayerLoopUpdate();
}

private void ShowPopup(string title, string message)
{
if (popupTitle != null) popupTitle.text = title;
if (popupMessage != null) popupMessage.text = message;
if (popup != null) popup.style.display = DisplayStyle.Flex;
}

private void ClosePopup(EventBase e)
{
if (popup != null) popup.style.display = DisplayStyle.None;
}

private void ShowLoadingAndExecute(Action action)
{
EditorApplication.update += OnEditorUpdate;
if (loadingPage != null) loadingPage.style.display = DisplayStyle.Flex;
action?.Invoke();
}

private void HideLoading()
{
EditorApplication.update -= OnEditorUpdate;
if (loadingPage != null) loadingPage.style.display = DisplayStyle.None;
}
}
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading