/// <summary>Attempts to authenticate a user using Oculus Rift user data.</summary>
        public static void AuthenticateWithOculusRiftUserData(string oculusUserNonce,
                                                              int oculusUserId,
                                                              string oculusUserAccessToken,
                                                              bool hasUserAcceptedTerms,
                                                              Action <UserProfile> onSuccess,
                                                              Action <WebRequestError> onError)
        {
            LocalUser.ExternalAuthentication = new ExternalAuthenticationData()
            {
                provider       = ExternalAuthenticationProvider.OculusRift,
                ticket         = oculusUserAccessToken,
                additionalData = new Dictionary <string, string>()
                {
                    { ExternalAuthenticationData.OculusRiftKeys.NONCE, oculusUserNonce },
                    { ExternalAuthenticationData.OculusRiftKeys.USER_ID, oculusUserId.ToString() },
                },
            };

            APIClient.RequestOculusRiftAuthentication(oculusUserNonce, oculusUserId, oculusUserAccessToken, hasUserAcceptedTerms,
                                                      (t) =>
            {
                LocalUser.OAuthToken       = t;
                LocalUser.WasTokenRejected = false;
                LocalUser.Save();

                UserAccountManagement.UpdateUserProfile(onSuccess, onError);
            },
                                                      onError);
        }
        // ---------[ MOD COLLECTION MANAGEMENT ]---------
        /// <summary>Add a mod to the subscribed list and modifies the queued actions accordingly.</summary>
        public static void SubscribeToMod(int modId)
        {
            // add sub to list
            if (!LocalUser.SubscribedModIds.Contains(modId))
            {
                LocalUser.SubscribedModIds.Add(modId);
            }

            // check queues
            bool unsubQueued = LocalUser.QueuedUnsubscribes.Contains(modId);
            bool subQueued   = LocalUser.QueuedSubscribes.Contains(modId);

            // add to/remove from queues
            if (unsubQueued)
            {
                LocalUser.QueuedUnsubscribes.Remove(modId);
            }
            else if (!subQueued)
            {
                LocalUser.QueuedSubscribes.Add(modId);
            }

            // save
            LocalUser.Save();
        }
        /// <summary>Begins the authentication process using a mod.io Security Code.</summary>
        public static void AuthenticateWithSecurityCode(string securityCode,
                                                        Action <UserProfile> onSuccess,
                                                        Action <WebRequestError> onError)
        {
            APIClient.GetOAuthToken(securityCode, (t) =>
            {
                LocalUser.OAuthToken       = t;
                LocalUser.WasTokenRejected = false;
                LocalUser.Save();

                UserAccountManagement.UpdateUserProfile(onSuccess, onError);
            },
                                    onError);
        }
        /// <summary>Attempts to authenticate a user using Xbox Live credentials.</summary>
        public static void AuthenticateWithXboxLiveToken(string xboxLiveUserToken,
                                                         Action <UserProfile> onSuccess,
                                                         Action <WebRequestError> onError)
        {
            LocalUser.ExternalAuthentication = new ExternalAuthenticationData()
            {
                ticket   = xboxLiveUserToken,
                provider = ExternalAuthenticationProvider.XboxLive,
            };

            APIClient.RequestXboxLiveAuthentication(xboxLiveUserToken, (t) =>
            {
                LocalUser.OAuthToken       = t;
                LocalUser.WasTokenRejected = false;
                LocalUser.Save();

                UserAccountManagement.UpdateUserProfile(onSuccess, onError);
            },
                                                    onError);
        }
        /// <summary>Attempts to authenticate a user using a GOG Encrypted App Ticket.</summary>
        public static void AuthenticateWithGOGEncryptedAppTicket(string encodedTicket,
                                                                 Action <UserProfile> onSuccess,
                                                                 Action <WebRequestError> onError)
        {
            LocalUser.ExternalAuthentication = new ExternalAuthenticationData()
            {
                ticket   = encodedTicket,
                provider = ExternalAuthenticationProvider.Steam,
            };

            APIClient.RequestGOGAuthentication(encodedTicket, (t) =>
            {
                LocalUser.OAuthToken       = t;
                LocalUser.WasTokenRejected = false;
                LocalUser.Save();

                UserAccountManagement.UpdateUserProfile(onSuccess, onError);
            },
                                               onError);
        }
        /// <summary>Attempts to authenticate a user using an itch.io JWT Token.</summary>
        public static void AuthenticateWithItchIOToken(string jwtToken,
                                                       bool hasUserAcceptedTerms,
                                                       Action <UserProfile> onSuccess,
                                                       Action <WebRequestError> onError)
        {
            LocalUser.ExternalAuthentication = new ExternalAuthenticationData()
            {
                ticket   = jwtToken,
                provider = ExternalAuthenticationProvider.ItchIO,
            };

            APIClient.RequestItchIOAuthentication(jwtToken, hasUserAcceptedTerms,
                                                  (t) =>
            {
                LocalUser.OAuthToken       = t;
                LocalUser.WasTokenRejected = false;
                LocalUser.Save();

                UserAccountManagement.UpdateUserProfile(onSuccess, onError);
            },
                                                  onError);
        }
        // ---------[ AUTHENTICATION ]---------
        /// <summary>Pulls any changes to the User Profile from the mod.io servers.</summary>
        public static void UpdateUserProfile(Action <UserProfile> onSuccess,
                                             Action <WebRequestError> onError)
        {
            if (LocalUser.AuthenticationState != AuthenticationState.NoToken)
            {
                APIClient.GetAuthenticatedUser((p) =>
                {
                    LocalUser.Profile = p;
                    LocalUser.Save();

                    if (onSuccess != null)
                    {
                        onSuccess(p);
                    }
                },
                                               onError);
            }
            else if (onSuccess != null)
            {
                onSuccess(null);
            }
        }
Example #8
0
        // ---------[ 2019 ]---------
        /// <summary>Moves the data from the UserAuthenticationData and ModManager caches to UserAccountManagement.</summary>
        private static void Update_2_0_to_2_1_UserData()
        {
            Debug.Log("[mod.io] Attempting 2.0->2.1 UserData update.");

            // check if the file already exists
            byte[] fileData = null;

            UserDataStorage.InitializeForUser(null, () => {});
            UserDataStorage.ReadFile(LocalUser.FILENAME, (success, data) => fileData = data);

            if (fileData != null && fileData.Length > 0)
            {
                Debug.Log("[mod.io] Aborting UserData update. FileExists: \'"
                          + LocalUser.FILENAME + "\' ["
                          + ValueFormatting.ByteCount(fileData.Length, null) + "]");
            }

            // update
            GenericJSONObject dataWrapper;
            LocalUser         userData = new LocalUser();
            string            filePath = null;

            // - copy enabled/subbed -
            filePath = ModManager.PERSISTENTDATA_FILEPATH;

            if (IOUtilities.TryReadJsonObjectFile(filePath, out dataWrapper))
            {
                int[] modIds = null;

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "subscribedModIds",
                                                 out modIds))
                {
                    userData.subscribedModIds = new List <int>(modIds);
                }

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "enabledModIds",
                                                 out modIds))
                {
                    userData.enabledModIds = new List <int>(modIds);
                }
            }

            // - copy queued subs/unsubs -
            filePath = IOUtilities.CombinePath(CacheClient.cacheDirectory,
                                               ModIO.UI.ModBrowser.MANIFEST_FILENAME);

            if (IOUtilities.TryReadJsonObjectFile(filePath, out dataWrapper))
            {
                List <int> modIds = null;

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "queuedSubscribes",
                                                 out modIds))
                {
                    userData.queuedSubscribes = new List <int>(modIds);
                }

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "queuedUnsubscribes",
                                                 out modIds))
                {
                    userData.queuedUnsubscribes = new List <int>(modIds);
                }
            }

            // - copy UAD -
            filePath = UserAuthenticationData.FILE_LOCATION;

            if (IOUtilities.TryReadJsonObjectFile(filePath, out dataWrapper))
            {
                // user profile
                int userId = UserProfile.NULL_ID;
                if (dataWrapper.data.ContainsKey("userId"))
                {
                    userId = (int)dataWrapper.data["userId"];
                }

                userData.profile = null;
                if (userId != UserProfile.NULL_ID)
                {
                    userData.profile = CacheClient.LoadUserProfile(userId);
                }

                // token data
                if (dataWrapper.data.ContainsKey("token"))
                {
                    userData.oAuthToken = (string)dataWrapper.data["token"];
                }
                if (dataWrapper.data.ContainsKey("wasTokenRejected"))
                {
                    userData.wasTokenRejected = (bool)dataWrapper.data["wasTokenRejected"];
                }

                // NOTE(@jackson): External Authentication is no longer saved to disk and is thus ignored.

                IOUtilities.DeleteFile(filePath);
            }

            // - set and save -
            LocalUser.instance = userData;
            LocalUser.isLoaded = true;
            LocalUser.Save();

            Debug.Log("[mod.io] UserData updated completed.");
        }
        /// <summary>Pushes queued subscribe actions to the server.</summary>
        public static void PushSubscriptionChanges(Action onCompletedNoErrors,
                                                   Action <List <WebRequestError> > onCompletedWithErrors)
        {
            int responsesPending = (LocalUser.QueuedSubscribes.Count
                                    + LocalUser.QueuedUnsubscribes.Count);

            // early outs
            if (LocalUser.AuthenticationState == AuthenticationState.NoToken ||
                responsesPending == 0)
            {
                if (onCompletedNoErrors != null)
                {
                    onCompletedNoErrors();
                }

                return;
            }

            // set up vars
            string userToken = LocalUser.OAuthToken;
            List <WebRequestError> errors = new List <WebRequestError>();

            List <int> subscribesPushed
                = new List <int>(LocalUser.QueuedSubscribes.Count);
            List <int> unsubscribesPushed
                = new List <int>(LocalUser.QueuedUnsubscribes.Count);

            // callback
            Action onRequestCompleted = () =>
            {
                if (responsesPending <= 0)
                {
                    if (userToken == LocalUser.OAuthToken)
                    {
                        foreach (int modId in subscribesPushed)
                        {
                            LocalUser.QueuedSubscribes.Remove(modId);
                        }
                        foreach (int modId in unsubscribesPushed)
                        {
                            LocalUser.QueuedUnsubscribes.Remove(modId);
                        }

                        LocalUser.Save();
                    }

                    if (errors.Count == 0 &&
                        onCompletedNoErrors != null)
                    {
                        onCompletedNoErrors();
                    }
                    else if (errors.Count > 0 &&
                             onCompletedWithErrors != null)
                    {
                        onCompletedWithErrors(errors);
                    }
                }
            };

            // - push -
            foreach (int modId in LocalUser.QueuedSubscribes)
            {
                APIClient.SubscribeToMod(modId,
                                         (p) =>
                {
                    subscribesPushed.Add(modId);

                    --responsesPending;
                    onRequestCompleted();
                },
                                         (e) =>
                {
                    // Error for "Mod is already subscribed"
                    if (e.webRequest.responseCode == 400)
                    {
                        subscribesPushed.Add(modId);
                    }
                    // Error for "Mod is unavailable"
                    else if (e.webRequest.responseCode == 404)
                    {
                        subscribesPushed.Add(modId);
                    }
                    // Error for real
                    else
                    {
                        errors.Add(e);
                    }

                    --responsesPending;
                    onRequestCompleted();
                });
            }
            foreach (int modId in LocalUser.QueuedUnsubscribes)
            {
                APIClient.UnsubscribeFromMod(modId,
                                             () =>
                {
                    --responsesPending;
                    unsubscribesPushed.Remove(modId);

                    onRequestCompleted();
                },
                                             (e) =>
                {
                    // Error for "Mod is already subscribed"
                    if (e.webRequest.responseCode == 400)
                    {
                        unsubscribesPushed.Remove(modId);
                    }
                    // Error for "Mod is unavailable"
                    else if (e.webRequest.responseCode == 404)
                    {
                        unsubscribesPushed.Remove(modId);
                    }
                    // Error for real
                    else
                    {
                        errors.Add(e);
                    }

                    --responsesPending;
                    onRequestCompleted();
                });
            }
        }
Example #10
0
        /// <summary>Attempts to reauthenticate using the stored external auth ticket.</summary>
        public static void ReauthenticateWithStoredExternalAuthData(bool hasUserAcceptedTerms,
                                                                    Action <UserProfile> onSuccess,
                                                                    Action <WebRequestError> onError)
        {
            ExternalAuthenticationData authData = LocalUser.ExternalAuthentication;

            Debug.Assert(!string.IsNullOrEmpty(authData.ticket));
            Debug.Assert(authData.provider != ExternalAuthenticationProvider.None);

            Action <string> onSuccessWrapper = (t) =>
            {
                LocalUser.OAuthToken       = t;
                LocalUser.WasTokenRejected = false;
                LocalUser.Save();

                if (onSuccess != null)
                {
                    UserAccountManagement.UpdateUserProfile(onSuccess, onError);
                }
            };

            switch (LocalUser.ExternalAuthentication.provider)
            {
            case ExternalAuthenticationProvider.Steam:
            {
                APIClient.RequestSteamAuthentication(authData.ticket,
                                                     hasUserAcceptedTerms,
                                                     onSuccessWrapper,
                                                     onError);
            }
            break;

            case ExternalAuthenticationProvider.GOG:
            {
                APIClient.RequestGOGAuthentication(authData.ticket,
                                                   hasUserAcceptedTerms,
                                                   onSuccessWrapper,
                                                   onError);
            }
            break;

            case ExternalAuthenticationProvider.ItchIO:
            {
                APIClient.RequestItchIOAuthentication(authData.ticket,
                                                      hasUserAcceptedTerms,
                                                      onSuccessWrapper,
                                                      onError);
            }
            break;

            case ExternalAuthenticationProvider.OculusRift:
            {
                string token        = authData.ticket;
                string nonce        = null;
                string userIdString = null;
                int    userId       = -1;
                string errorMessage = null;

                if (authData.additionalData == null)
                {
                    errorMessage = "The user id and nonce are missing.";
                }
                else if (!authData.additionalData.TryGetValue(ExternalAuthenticationData.OculusRiftKeys.NONCE, out nonce) ||
                         string.IsNullOrEmpty(nonce))
                {
                    errorMessage = "The nonce is missing.";
                }
                else if (!authData.additionalData.TryGetValue(ExternalAuthenticationData.OculusRiftKeys.USER_ID, out userIdString) ||
                         string.IsNullOrEmpty(userIdString))
                {
                    errorMessage = "The user id is missing.";
                }
                else if (!int.TryParse(userIdString, out userId))
                {
                    errorMessage = "The user id is not parseable as an integer.";
                }

                if (errorMessage != null)
                {
                    Debug.LogWarning("[mod.io] Unable to authenticate using stored Oculus Rift user data.\n"
                                     + errorMessage);

                    if (onError != null)
                    {
                        var error = WebRequestError.GenerateLocal(errorMessage);
                        onError(error);
                    }

                    return;
                }
                else
                {
                    APIClient.RequestOculusRiftAuthentication(nonce, userId, token,
                                                              hasUserAcceptedTerms,
                                                              onSuccessWrapper,
                                                              onError);
                }
            }
            break;

            case ExternalAuthenticationProvider.XboxLive:
            {
                APIClient.RequestXboxLiveAuthentication(authData.ticket,
                                                        hasUserAcceptedTerms,
                                                        onSuccessWrapper,
                                                        onError);
            }
            break;

            default:
            {
                throw new System.NotImplementedException();
            }
            }
        }
Example #11
0
        /// <summary>Pulls the subscriptions from the server and stores the changes.</summary>
        public static void PullSubscriptionChanges(Action <List <ModProfile> > onSuccess,
                                                   Action <WebRequestError> onError)
        {
            // early out
            if (LocalUser.AuthenticationState == AuthenticationState.NoToken)
            {
                if (onSuccess != null)
                {
                    onSuccess(new List <ModProfile>(0));
                }
                return;
            }

            // holding vars
            string            userToken = LocalUser.OAuthToken;
            List <ModProfile> remoteOnlySubscriptions = new List <ModProfile>();

            // set filter and initial pagination
            RequestFilter subscriptionFilter = new RequestFilter();

            subscriptionFilter.AddFieldFilter(ModIO.API.GetUserSubscriptionsFilterFields.gameId,
                                              new EqualToFilter <int>(PluginSettings.GAME_ID));

            APIPaginationParameters pagination = new APIPaginationParameters()
            {
                limit  = APIPaginationParameters.LIMIT_MAX,
                offset = 0,
            };

            // define actions
            Action getNextPage = null;
            Action <RequestPage <ModProfile> > onPageReceived = null;
            Action onAllPagesReceived = null;

            getNextPage = () =>
            {
                APIClient.GetUserSubscriptions(subscriptionFilter, pagination,
                                               (response) =>
                {
                    onPageReceived(response);

                    // check if all pages received
                    if (response != null &&
                        response.items != null &&
                        response.items.Length > 0 &&
                        response.resultTotal > response.size + response.resultOffset)
                    {
                        pagination.offset = response.resultOffset + response.size;

                        getNextPage();
                    }
                    else
                    {
                        onAllPagesReceived();

                        if (onSuccess != null)
                        {
                            onSuccess(remoteOnlySubscriptions);
                        }
                    }
                },
                                               (e) =>
                {
                    if (onError != null)
                    {
                        onError(e);
                    }
                });
            };


            onPageReceived = (r) =>
            {
                foreach (ModProfile profile in r.items)
                {
                    if (profile != null)
                    {
                        remoteOnlySubscriptions.Add(profile);
                    }
                }
            };

            onAllPagesReceived = () =>
            {
                if (userToken != LocalUser.OAuthToken)
                {
                    return;
                }

                List <int> localOnlySubs
                    = new List <int>(LocalUser.SubscribedModIds);

                // NOTE(@jackson): Unsub actions *should not* be found in activeUser.subscribedModIds
                foreach (int modId in LocalUser.QueuedUnsubscribes)
                {
                    #if DEBUG
                    if (localOnlySubs.Contains(modId))
                    {
                        Debug.LogWarning("[mod.io] A locally subscribed mod was found in the"
                                         + " queuedUnsubscribes. This should not occur - please"
                                         + " ensure that any mod ids added to"
                                         + " activeUser.queuedUnsubscribes are removed from"
                                         + " activeUser.subscribedModIds or use"
                                         + " UserAccountManagement.UnsubscribeFromMod() to handle"
                                         + " this automatically.");
                    }
                    #endif

                    localOnlySubs.Remove(modId);
                }

                List <int> newSubs = new List <int>();

                // build new subs list
                for (int i = 0; i < remoteOnlySubscriptions.Count; ++i)
                {
                    ModProfile profile = remoteOnlySubscriptions[i];

                    // remove if in queued subs
                    LocalUser.QueuedSubscribes.Remove(profile.id);

                    // if in unsub queue
                    if (LocalUser.QueuedUnsubscribes.Contains(profile.id))
                    {
                        remoteOnlySubscriptions.RemoveAt(i);
                        --i;
                    }
                    // if locally subbed
                    else if (localOnlySubs.Remove(profile.id))
                    {
                        remoteOnlySubscriptions.RemoveAt(i);
                        --i;
                    }
                    // if not locally subbed && if not in unsub queue
                    else
                    {
                        newSubs.Add(profile.id);
                    }
                }

                // -- update locally --
                // remove new unsubs
                foreach (int modId in localOnlySubs)
                {
                    // if not in sub queue
                    if (!LocalUser.QueuedSubscribes.Contains(modId))
                    {
                        LocalUser.SubscribedModIds.Remove(modId);
                    }
                }

                LocalUser.SubscribedModIds.AddRange(newSubs);

                // save
                LocalUser.Save();
            };

            // get pages
            getNextPage();
        }